Deserializing JSON Without Unique Property Name

痴心易碎 提交于 2019-12-10 18:13:33

问题


I have a json string that looks like the following

{
    "1ST": {
        "name": "One",
        "symbol": "1st"
    },
    "2ND": {
        "name": "Two",
        "symbol": "2nd"
    }
}

Im trying to Serialize it down to a C# object. It looks like it is creating a Dictionary, so i have created the following structure

public class Response
{
    public Dictionary<string, Item> Objects { get; set; }
}

public class Item
{
    public string name { get; set; }
    public string symbol { get; set; }
}

And during serialization running the following

response = JsonConvert.DeserializeObject<Response>(jsonString);

It doesnt throw an error on Deserialization, but my response just comes back as null. What am i missing?


回答1:


You've got the right basic idea, but you've got an extra Objects property that you don't really want: your JSON is the dictionary, effectively. You can deserialize it directly to a Dictionary<string, Item>>. Here's an example:

using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;

public class Item
{
    public string Name { get; set; }
    public string Symbol { get; set; }

    public override string ToString() => $"{Name}/{Symbol}";
}

public class Test
{
    static void Main()
    {
        var json = File.ReadAllText("test.json");
        var dictionary = JsonConvert.DeserializeObject<Dictionary<string, Item>>(json);
        foreach (var entry in dictionary)
        {
            Console.WriteLine($"{entry.Key}: {entry.Value}");
        }
    }
}

Output:

1ST: One/1st
2ND: Two/2nd

Now if you need your Response type, there are various options:

  • Make that derive from Dictionary<string, Item> and remove the Objects property. (Not good if you need the Objects property.)
  • Deserialize to the dictionary, but then create a new Response object and assign the property yourself. (Not good if the response is part of another type.)
  • Investigate whether there's some attribute for Json.NET to treat Objects as a sort of "root" property.

I've had some luck with the last aspect, but not a complete solution. If you change Objects to a Dictionary<string, JToken> then you can apply the [JsonExtensionData] to it, which makes it act as a default dictionary for any unmatched property. However, I haven't found a way of persuading Json.NET to use that attribute and perform the appropriate conversion. You could create a dictionary which performed the conversion from JToken to Item (using regular Json.NET code) every time an entry was added to it, and then added that value to another dictionary - but that's pretty ugly. This may just be a case that Json.NET doesn't handle.




回答2:


Using strong type object is recommended but another approach you can use dynamic type that will be evaluate during runtime.

Please take a look the code below.

Please note that I change variable name because we cannot define variable start with numeric in C#.

using Newtonsoft.Json;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var jsonString = @"{
                            'First': {
                                'name': 'One',
                                'symbol': '1st'
                            },
                            'Second': {
                                'name': 'Two',
                                'symbol': '2nd'
                            }
                        }";

            //If you want to access using strong type.
            var response = JsonConvert.DeserializeObject<Response>(jsonString);
            var secondSymbol = response.Second.symbol.ToString();
            System.Console.WriteLine(secondSymbol);

            //If you want to access using dynamic type, will evalute in runtime.
            var responseDynamic = JsonConvert.DeserializeObject<dynamic>(jsonString);
            var secondSymbolDynamic = responseDynamic.Second.symbol.ToString() ;
            System.Console.WriteLine(secondSymbolDynamic);

            System.Console.ReadLine();
        }

        public class Response
        {
            public Item First { get; set; }
            public Item Second { get; set; }
        }

        public class Item
        {
            public string name { get; set; }
            public string symbol { get; set; }
        }
    }
}

Hope it will be useful. :)



来源:https://stackoverflow.com/questions/49932943/deserializing-json-without-unique-property-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!