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

Jus*_*tin 5 c# json json.net json-deserialization

我有一个如下所示的 json 字符串

{
    "1ST": {
        "name": "One",
        "symbol": "1st"
    },
    "2ND": {
        "name": "Two",
        "symbol": "2nd"
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

public class Item
{
    public string name { get; set; }
    public string symbol { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

在序列化期间运行以下命令

response = JsonConvert.DeserializeObject<Response>(jsonString);
Run Code Online (Sandbox Code Playgroud)

它不会在反序列化时抛出错误,但我的响应只是返回为空。我缺少什么?

Jon*_*eet 6

您的基本想法是正确的,但您有一个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}");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

1ST: One/1st
2ND: Two/2nd
Run Code Online (Sandbox Code Playgroud)

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

  • 使其派生自该属性Dictionary<string, Item>并删除该Objects属性。(如果您需要该财产,那就不好了Objects。)
  • 反序列化到字典,然后创建一个新Response对象并自己分配属性。(如果响应是另一种类型的一部分,则不好。)
  • 调查 Json.NET 是否有某些属性被视为Objects一种“根”属性。

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