Parse this JSON file

Hey,
This is probably quite simple for some but I have spent many hours on this now and really hope someone can help out.
I’m trying to use this JSON file I get from an API. I am even unsure IF the Unity JSONUtility is capable of parsing this JSON at all?

{
“products”: [
{
"id": “53265269”,
“productNumber”: {
"value": “43-67-225-25”,
"formatted": "9436722525”
},
"name": “Lorem Ipsum“,
"description": "Lorem Ipsum",
“price”: {
"amount": 4,
"currencyCode": “USD”
},
“sellingPrice”: {
"amount": 5,
"currencyCode": “USD”
},
“manufaturer”: {
"name": “John”,
“location”: “DE”
},
"_links": {
“website”: {
"href": “https//www.loremipsum.com”,
"method": "GET"
}
}
},

//MORE PRODUCTS HERE.

]
}

And how would I have to set up the class to map it into?
This is the class I made, but I only get “Null” when trying to debug anything.

[System.Serializable]
public class Product
{
    public string id;
    public string productNumber;
    public string description;
    public string product;
    public string type;



    //Constructor
    public Product(Product product)
    {
        this.id = product.id;
        this.productNumber = product.productNumber;
        this.description = product.description;
        this.product = product.product;
        this.type = product.type;

    }

}

Anything inside braces - { and } - is an object. So the entire file is an object with a single property “products” which is an array. The array is a list of objects. Each of those objects has some individual fields (id, name, description), and also several fields which are themselves objects (productNumber, price, sellingPrice, links).

Your C# class will need to replicate the same structure, so for example you’ll need a ProductNumber class which has Value and Formatted fields, and your Product class would have a productNumber property of type ProductNumber.

There’s a bit of ambiguity on some of the fields - whether they should be considered classes or Dictionaries, which have the same representation in JSON. For instance, the _links field:

class Link {
   public string href;
   public string method;
}

// Method A:
public Links _links;
public class Links {
   Link website;
}

// Method B:
public Dictionary<string,Link> _links;

// Method C:
public Dictionary<string,Dictionary<string,string>> _links;

So if you have any documentation for what this JSON is supposed to contain, that would be a good place to start.

download the “JsonFx.Json” package and use this code to read json data.

using JsonFx.Json;
public class jsonPickle{
        static public string dumps(object ht)
        {
            string data = JsonWriter.Serialize(ht);
            //string data = Convert.ToBase64String(data);
            return data;
        }
    
    
        static public object loads(string data)
        {
            object ht = JsonReader.Deserialize<object>(data);
            return ht;
        }
    }

Use like this jsonPickle.loads(data) returns as object Hashtable I believe…

JsonUtility can’t handle a Dictionary so you’ll have to use strong named classes:

public class ProductCollection
{
    public List<Product> products {get; set;}
}

public class Product
{
       public int id {get; set;}
       public string name {get; set;}
       public string description {get; set;}
       public ProductNumber productNumber {get; set;}
       public PriceDefinition price {get; set;}
       public PriceDefinition sellingPrice {get; set;}
       public Manufacturer manufacturer {get; set;}
       public Links _links {get; set;} 
}

public struct ProductNumber
{
        public string value {get; set;}
        public string formatted {get; set;}
}

public struct PriceDefinition
{
        public decimal amount {get; set;}
        public string currencyCode {get; set;}
}

public struct Manufacturer
{
        public string name {get; set;}
        public string location {get; set;}
}

public struct Links
{
        public Website website {get; set;}
}

public struct Website
{
        public string href {get; set;}
        public string method {get; set;}
}

Of course those structs could be classes. Using structs results in less GC allocation but makes them default to byval instead of byref and more expensive when passing them to methods.

These structure should be simple enough with JsonUtility. With JSON .NET it would be simply:

var prodCollection = JsonConvert.DeserializeObject<ProductCollection>(jsonString);
1 Like

I really like the json.net asset, but you should be able to use unitys json also if you just need a free version. Also note a good link is
http://json2csharp.com/

If you toss your json file into it, it will then spit out the classes and properties you need for you so you know how to structure your class to deserialize into.

There is also

Which will help you track down an error in your json structure if it fails.

1 Like

Thanks, :slight_smile: And yeah that’s why I gave the class approach and said it would be simple enough with JsonUtility (that’s Unity’s Json).

Also, you have to be careful with json2csharp… it’s awesome but you still need to do some tweaking afterwards.

Thanks a lot everyone, I think I have gotten further. I went for Dustin’s class setup.

So now I am trying to access the data, but am failing so far:

    void Start(){
        //get local JSON file from Resources folder
        string json = getJsonData ();

        ProductCollection data = JsonUtility.FromJson<ProductCollection>(json);
    
        //Test the ID
        Debug.Log (data.products[1].id);
}

I suppose this is wrong?

data.products.Count; gives a NullReferenceException…

We’d have to see your json string… what is accounts? The original json you posted doesn’t have any “accounts” property.

That “Account” was a poor copy from another test (I was trying with another more simple setup).

So the structure is:

[Serializable]
public class ProductCollection
{
    public List<Product> products {get; set;}
}
[Serializable]
public class Product
{
       public int id {get; set;}
       public string name {get; set;}
       public string description {get; set;}
       public ProductNumber productNumber {get; set;}
       public PriceDefinition price {get; set;}
       public PriceDefinition sellingPrice {get; set;}
       public Manufacturer manufacturer {get; set;}
       public Links _links {get; set;}
}
[Serializable]
public struct ProductNumber
{
        public string value {get; set;}
        public string formatted {get; set;}
}
[Serializable]
public struct PriceDefinition
{
        public decimal amount {get; set;}
        public string currencyCode {get; set;}
}
[Serializable]
public struct Manufacturer
{
        public string name {get; set;}
        public string location {get; set;}
}
[Serializable]
public struct Links
{
        public Website website {get; set;}
}
[Serializable]
public struct Website
{
        public string href {get; set;}
        public string method {get; set;}
}

And then I try to get any variable displayed in the Debug, but I fail…

    void Start(){
        //get local JSON file from Resources folder
        string json = getJsonData ();

        ProductCollection data = JsonUtility.FromJson<ProductCollection>(json);
  
        //Test if JsonUtility has worked??
        Debug.Log (data.products[1].id);
}

I can’t seem to access the variables in any way. I suspect it’s not working.
tried:
Debug.Log (data.products[1].id) → console says: NullReferenceException
Debug.Log (data.products.Count) → console says: NullReferenceException
Debug.Log (data) → console says: AccountCollection

Any tips on debugging the JsonUtility?

I believe you have to use the SerializableField attribute on properties for them to be properly serializable in Unity.

Try this instead:

[Serializable]
public class ProductCollection
{
    public List<Product> products;
}
[Serializable]
public class Product
{
       public int id;
       public string name;
       public string description;
       public ProductNumber productNumber;
       public PriceDefinition price;
       public PriceDefinition sellingPrice;
       public Manufacturer manufacturer;
       public Links _links;
}
[Serializable]
public struct ProductNumber
{
        public string value;
        public string formatted;
}
[Serializable]
public struct PriceDefinition
{
        public decimal amount;
        public string currencyCode;
}
[Serializable]
public struct Manufacturer
{
        public string name;
        public string location;
}
[Serializable]
public struct Links
{
        public Website website;
}
[Serializable]
public struct Website
{
        public string href;
        public string method;
}

YES!! taking away {get; set;} made it work! Thank you everybody! Now I can have a peaceful weekend!!! :slight_smile: :slight_smile:

1 Like