2

How to use json.net(JObject/Jarray/Jtoken) and convert to class in the fastest(performance) way into a dictionary? the key of the dictionary is the sees "name" in the json file

Can anyone help?

Thanks alot!

seed.json
       {
          "Seed": [
                {
                    "name": "Cheetone",
                    "growthrate": 1,
                    "cost": 500
                },
                {
                    "name": "Tortone",
                    "growthrate": 8,
                    "cost": 100
                }
            ],
        }


    public class SoilStat
    {
        public int growthRate;
        public int cost;
    }

    public class DataLoader : MonoSingleton<DataLoader>
    {
        public string txt;
        Dictionary<string, SoilStat> _soilList = new Dictionary<string, SoilStat>();

        JObject rawJson = JObject.Parse(txt);

        ???
    }
phongyewtong
  • 5,085
  • 13
  • 56
  • 81
  • What is `_txtAsset`? Is it that snippet of JSON at the top? If so, can you please provide the actual valid JSON you are using? (as it is, it's malformed) – Kirk Woll Dec 15 '15 at 01:24
  • Your question sounds very general but the actual code you show seems not to be so. What are the dictionary keys supposed to be? – dbc Dec 15 '15 at 01:24
  • updated the code @dbc – phongyewtong Dec 15 '15 at 01:44
  • By "fastest" do you mean "most performant" or "most straightforward"? – dbc Dec 15 '15 at 01:54
  • Then I may point you to [Which is faster?](http://ericlippert.com/2012/12/17/performance-rant/) by [Eric Lippert](http://stackoverflow.com/users/88656/eric-lippert). I can give you a very simple way to do what you want but you'll need to do performance testing yourself. Want it? – dbc Dec 15 '15 at 01:57
  • Yes want it! thanks! @dbc – phongyewtong Dec 15 '15 at 01:59

2 Answers2

2

A simple way to do what you want is to use SelectTokens to pick out the portions of JSON of interest to you, then just deserialize those bits. Thus:

        var rawJson = JObject.Parse(txt);
        var _soilList = rawJson.SelectTokens("Seed[*]").ToDictionary(t => t["name"], t => t.ToObject<SoilStat>());

A more complex solution would be to create DTO objects for deserialization then map them to your desired classes:

public class NamedSoilStat : SoilStat
{
    public string name { get; set; }
}

public class RootObject
{
    public RootObject() { this.Seed = new List<NamedSoilStat>(); }
    public List<NamedSoilStat> Seed { get; set; }
}

And then:

        var root = JsonConvert.DeserializeObject<RootObject>(txt);
        var _soilList = root.Seed.ToDictionary(t => t.name, t => new SoilStat { cost = t.cost, growthRate = t.growthRate });

As to which is more performant, you would need to test for yourself.

Incidentally, if your txt JSON string is coming from a file, and is large, you should consider streaming it in rather than reading it into an intermediate string. See Performance Tips: Optimize Memory Usage.

Community
  • 1
  • 1
dbc
  • 104,963
  • 20
  • 228
  • 340
  • I cant use selecttoken due to some restriction on unity5. is there other way to do it without creating DTO object? @dbc – phongyewtong Dec 27 '15 at 04:09
1

In my experiences, using JsonConvert is significantly faster than using JObject.Parse(). See this page for a performance comparison (on Windows Phone, but I'd imagine it would be similar on desktop), and linked from that page is an example that uses JsonConvert.

gregstoll
  • 1,318
  • 9
  • 14