在没有唯一属性名称的情况下反序列化JSON

时间:2018-04-20 02:23:08

标签: c# json json.net json-deserialization

我有一个类似于以下

的json字符串
{
    "1ST": {
        "name": "One",
        "symbol": "1st"
    },
    "2ND": {
        "name": "Two",
        "symbol": "2nd"
    }
}

我试图将其序列化为C#对象。看起来它正在创建一个Dictionary,所以我创建了以下结构

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

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

在序列化期间运行以下

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

它不会在反序列化时抛出错误,但我的响应只是返回null。我错过了什么?

2 个答案:

答案 0 :(得分:2)

您已经拥有了正确的基本想法,但您已经获得了一个您并不真正想要的额外Objects财产:您的JSON 字典,有效。您可以将其直接反序列化为Dictionary<string, Item>>。这是一个例子:

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}");
        }
    }
}

输出:

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

现在,如果您需要您的Response类型,则有多种选择:

  • Dictionary<string, Item>派生并删除Objects属性。 (如果您需要Objects属性,则不太好。)
  • 反序列化到字典,但随后创建一个新的Response对象并自行分配属性。 (如果响应是另一种类型的一部分,那就不好了。)
  • 调查Json.NET是否有某些属性将Objects视为一种&#34; root&#34;属性。

我在最后一个方面已经一些运气,但不是一个完整的解决方案。如果您将Objects更改为Dictionary<string, JToken>,则可以将[JsonExtensionData]应用于该JToken,这使其可以充当任何不匹配属性的默认字典。但是,我还没有找到一种方法来说服Json.NET使用该属性执行适当的转换。您可以创建一个字典,在每次添加条目时执行从Item到{{1}}的转换(使用常规Json.NET代码),然后将该值添加到另一个字典 - 但是&# 39;非常丑陋。这可能只是Json.NET无法处理的情况。

答案 1 :(得分:0)

建议使用强类型对象,但另一种方法是使用将在运行时评估的动态类型。

请查看下面的代码。

请注意我更改变量名称是因为我们无法在C#中使用numeric定义变量start。

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; }
        }
    }
}

希望它会有用。 :)