c# - 如何使用 json.NET 反序列化动态命名的根节点

标签 c# json.net deserialization

这是 json 文件的示例:

{
   "John Smith": {
      "id": "72389",
      "email": "johnsmith@gmail.com",
      "books": [
         {
            "id": "0",
            "title": "The Hunger Games",
            "rating": "5"
         },
         {
            "id": "1",
            "title": "Harry Potter and the Order of the Phoenix",
            "rating": "3"
         },
      ],
      "magazines": [
         {
            "id": "2",
            "title": "National Geographic",
            "rating": "1"
         },
         {
            "id": "3",
            "title": "Wired",
            "rating": "4"
         }
      ],
   }
}

注意根节点有一个动态名称 (John Smith),我需要反序列化的每个 json 都有一个不同的名称。 此 json 结构需要按如下方式设置类:

public class RootObject
{
    public JohnSmith { get; set; }
}

public class JohnSmith //oops
{
    public string id { get; set; }
    public string email { get; set; }
    public List<Book> books { get; set; }
    public List<Magazine> magazines { get; set; }
}

public class Book
{
    public string id { get; set; }
    public string title { get; set; }
    public string rating { get; set; }
}

public class Magazine
{
    public string id { get; set; }
    public string title { get; set; }
    public string rating { get; set; }
}

我的目标是反序列化“绕过/忽略”根对象,最重要的是动态命名的节点。这并不重要,但我希望能够获取姓氏并将其设置为 Person 类的属性。

public class Person
{
    public string id { get; set; }
    public string email { get; set; }
    public string name { get; set; }
    public List<Book> books { get; set; }
    public List<Magazine> magazines { get; set; }
}

public class Book
{
    public string id { get; set; }
    public string title { get; set; }
    public string rating { get; set; }
}

public class Magazine
{
    public string id { get; set; }
    public string title { get; set; }
    public string rating { get; set; }
}

这是我现在的做法:

var jo = JObject.Parse(json);
var deserializable = jo.First.First.ToString();

string name;
var jp = (JProperty)jo.First;
if (jp != null) name = jp.Name;

var person = JsonConvert.DeserializeObject<Person>(deserializable);
person.name = name;

这工作正常,但我想知道,也许使用自定义 JsonConverter 可以做得更好?恐怕这有点超出我的理解,所以我在这里寻求帮助......

无论如何,如果有更好的方法来实现这一点,请分享。

最佳答案

我会保留您的解决方案的第一部分(反序列化为 JObject),但我不会进行其他序列化。我的代码如下所示:

var jo = JObject.Parse(json);
var jp = jo.Properties().First();
var name = jp.Name;
var person = jp.Value.ToObject<Person>();

编辑:

如果您需要自定义转换器,可以使用以下代码。转换器将您的对象转换为 Person 列表,其中每个属性代表另一个 Person

class PersonListConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var list = (PersonList) value;

        writer.WriteStartObject();

        foreach (var p in list.Persons)
        {
            writer.WritePropertyName(p.Name);
            serializer.Serialize(writer, p);
        }

        writer.WriteEndObject();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jo = serializer.Deserialize<JObject>(reader);
        var result = new PersonList();
        result.Persons = new List<Person>();

        foreach (var prop in jo.Properties())
        {
            var p = prop.Value.ToObject<Person>();
            // set name from property name
            p.Name = prop.Name;
            result.Persons.Add(p);
        }

        return result;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(PersonList);
    }
}

PersonList 看起来像这样:

[JsonConverter(typeof(PersonListConverter))]
class PersonList
{
    public List<Person> Persons { get; set; }
}

关于c# - 如何使用 json.NET 反序列化动态命名的根节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23648193/

相关文章:

c# - 使用 C# 从 NHibernate 连接到 AS400 (iSeries) 时出现错误 RROR [08001] [IBM] SQL30081N

c# - 从未使用过 Resharper 方法

c# - 枚举上的 JsonConverter 属性打破了 asp.net 核心模型绑定(bind)

c# - 使用自动修剪字符串反序列化 json

C# 将Json字符串转为对象

c# - 如何在 C# 中反序列化包含多种类型元素的 XML 数组

java - org.apache.commons.lang.SerializationException : java. lang.ClassNotFoundException 异常

c# - 为什么我不能使用带有显式运算符的接口(interface)?

c# - 如何为我不拥有的类型和属性实现 TypeConverter?

java - 如何在 Java 中使用 spring.cloud 反序列化/序列化 Azure 服务总线