gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 21:12:52 24 4
gpt4 key购买 nike

这是 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com