相关文章推荐
另类的开水瓶  ·  c# unity3d ...·  1小时前    · 
果断的围巾  ·  OpenXml ...·  11 分钟前    · 
阳刚的青蛙  ·  NetCore使用DotNetCore.CA ...·  1 月前    · 
纯真的领结  ·  springboot ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

In a Windows Phone app using C#, I am trying to deserialize some JSON with the following structure:

[ { "kite" : { "supplier" : "ABC",
        "currency" : "GBP",
        "cost" : "7.98"
  { "puzzle" : { "supplier" : "DEF",
        "currency" : "USD",
        "cost" : "7.98"
  { "ball" : { "supplier" : "DEF",
        "currency" : "USD",
        "cost" : "5.49"

This is a list of toys in which the names of the toys (kite, puzzle, ball) are not known in advance. I don't have any control over the format of the JSON.

Using json2csharp.com I get the following classes:

public class Kite
    public string supplier { get; set; }
    public string currency { get; set; }
    public string cost { get; set; }
public class Puzzle
public class Ball
public class RootObject
    public Kite kite { get; set; }
    public Puzzle puzzle { get; set; }
    public Ball ball { get; set; }

This looks to me like an array of "toy" objects but I don't know what approach to take when deserializing this.

The only code that I have had work is the basic:

var root = JsonConvert.DeserializeObject(rawJSON);

I thought something like the following might work, but I would lose the name of the toy if it worked (and it doesn't):

public class Toy
    public string supplier { get; set; }
    public string currency { get; set; }
    public string cost { get; set; }
List<Toy> toyList = (List<Toy>) JsonConvert.DeserializeObject(rawJSON, typeof(List<Toy>));

Any suggestions please?

It looks like it would naturally be a Dictionary. Kite, puzzle, and ball would be keys. The values would be some type if object with supplier, currency, and cost properties. I can't investigate how to deserialize that at the moment, though. I'd look into using some kind of dynamic object, though, and perhaps translate it into something more concrete. – Dr. Wily's Apprentice Oct 10, 2013 at 22:24

You are close. If you define your Toy class as you have it in your question, you can deserialize into a List<Dictionary<string, Toy>>. Thus, each toy is actually represented by a Dictionary with a single entry in it. The Key is the name of the toy and the Value is the Toy info.
Here is a demo:

string json = @"
[ { ""kite"" : { ""supplier"" : ""ABC"",
        ""currency"" : ""GBP"",
        ""cost"" : ""7.98""
  { ""puzzle"" : { ""supplier"" : ""DEF"",
        ""currency"" : ""USD"",
        ""cost"" : ""7.98""
  { ""ball"" : { ""supplier"" : ""DEF"",
        ""currency"" : ""USD"",
        ""cost"" : ""5.49""
List<Dictionary<string, Toy>> list = 
       JsonConvert.DeserializeObject<List<Dictionary<string, Toy>>>(json);
foreach (Dictionary<string, Toy> dict in list)
    KeyValuePair<string, Toy> kvp = dict.First();
    Console.WriteLine("toy: " + kvp.Key);
    Console.WriteLine("supplier: " + kvp.Value.Supplier);
    Console.WriteLine("cost: " + kvp.Value.Cost + " (" + kvp.Value.Currency + ")");
    Console.WriteLine();

This outputs the following:

toy: kite
supplier: ABC
cost: 7.98 (GBP)
toy: puzzle
supplier: DEF
cost: 7.98 (USD)
toy: ball
supplier: DEF
cost: 5.49 (USD)

Admittedly, this solution is kind of "clunky", because it would be better to have the name of the toy included in the Toy class itself rather than have an intervening Dictionary to stumble over. There are two ways to fix this. One way is to add a Name property on the Toy class, deserialize into the same structure as shown above, then do a little bit of post-processing to move the names from each Dictionary into the respective Toy, building a new List<Toy> in the process. The second way to do it is to create a custom JsonConverter to handle this translation during deserialization. I'd be happy to demonstrate either of these alternate approaches if you wish. Just let me know. If you just need quick-and-dirty, then the above approach should do.

Alternative approach using a custom JsonConverter

This approach is a little "cleaner" because we can keep all the Toy info together on a single strongly-typed object, and keep all the deserialization logic separate so it doesn't clutter up the main code.

First, we need to alter your Toy class to give it a Name property.

class Toy
    public string Name { get; set; }
    public string Supplier { get; set; }
    public string Currency { get; set; }
    public decimal Cost { get; set; }

Next, we create a class which inherits from JsonConverter.

class ToyConverter : JsonConverter
    public override bool CanConvert(Type objectType)
        // This lets JSON.Net know that this converter can handle Toy objects
        return (objectType == typeof(Toy));
    public override object ReadJson(JsonReader reader, 
        Type objectType, object existingValue, JsonSerializer serializer)
        // load the toy JSON object into a JObject
        JObject jo = JObject.Load(reader);
        // get the first (and only) property of the object
        JProperty prop = jo.Properties().First();
        // deserialize the value of that property (which is another
        // object containing supplier and cost info) into a Toy instance
        Toy toy = prop.Value.ToObject<Toy>();
        // get the name of the property and add it to the newly minted toy
        toy.Name = prop.Name;
        return toy;
    public override void WriteJson(JsonWriter writer, 
        object value, JsonSerializer serializer)
        // If you need to serialize Toys back into JSON, then you'll need
        // to implement this method.  We can skip it for now.
        throw new NotImplementedException();

To use the converter, we just need to create an instance of it and pass it in the call to DeserializeObject<T>(). Now that we have this converter, we can deserialize directly into a List<Toy>, which is much more natural.

List<Toy> toys = JsonConvert.DeserializeObject<List<Toy>>(json, new ToyConverter());

Accessing the toy data from there is straightforward.

foreach (Toy toy in toys)
    Console.WriteLine("toy: " + toy.Name);
    Console.WriteLine("supplier: " + toy.Supplier);
    Console.WriteLine("cost: " + toy.Cost + " (" + toy.Currency + ")");
    Console.WriteLine();

You'll notice this gives exactly the same output as the previous example, but the code is much cleaner.

Brian, I won't get a change to test your suggestion above until later but it looks great! I would be very interested in seeing how you would use a custom JsonConverter please as that is not something I am familiar with. – John Oct 11, 2013 at 1:02

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.