gpt4 book ai didi

c# - 使用自定义格式作为引用时,如何使用 Json.NET 通过引用反序列化对象?

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

我有以下格式的 JSON:

{
"users": [
{
"first_name": "John",
"last_name": "Smith",
"vet": [ "FOO", "VET-1" ],
"animals": [ [ "FOO", "ANIMAL-22" ] ]
},
{
"first_name": "Susan",
"last_name": "Smith",
"vet": [ "FOO", "VET-1" ]
}
],
"BAR": {
"VET-1": {
"vet_name": "Acme, Inc",
"vet_id": 456
},
"ANIMAL-22": {
"animal_name": "Fido",
"species": "dog",
"animal_id": 789,
"vet": [ "FOO", "VET-1" ]
}
}
}

某些嵌套对象或多次引用的对象被序列化为引用。

然后引用的对象包含在 JSON 对象末尾的 BAR 数组中,并由 [ "FOO", "ANIMAL-22"]数组。

(FOOBAR 都是静态常量,ANIMAL-22/VET-1 标识符是半随机的)

不幸的是,这与 Json.NET 已经 serializes/deserializes referenced objects 的方式不匹配,而我可以实现的 IReferenceResolver 似乎不允许我充分调整行为(首先是 it's fixed to use "$ref")。

我还尝试为受影响的属性编写自定义 JsonConverter,但我似乎无法获得对根对象的 BAR 属性的引用。

有什么方法可以覆盖 Json.NET 以将上面的 JSON 反序列化为这种 C# 类结构?

public class User
{
[JsonProperty("first_name")]
public string FirstName { get; set; }

[JsonProperty("last_name")]
public string LastName { get; set; }

[JsonProperty("vet")]
public Vet Vet { get; set; }

[JsonProperty("animals")]
public List<Animal> Animals { get; set; }
}

public class Vet
{
[JsonProperty("vet_id")]
public int Id { get; set; }

[JsonProperty("vet_name")]
public string Name { get; set; }
}

public class Animal
{
[JsonProperty("animal_id")]
public int Id { get; set; }

[JsonProperty("animal_name")]
public string Name { get; set; }

[JsonProperty("vet")]
public Vet Vet { get; set; }

[JsonProperty("species")]
public string Species { get; set; }
}

编辑 #1: 虽然我在我的示例中只给出了 AnimalVet,但是有大量类型以这种方式引用我认为我需要一个“通用”或类型不可知的解决方案来处理数组结构 [ "FOO", "..."] 的任何此类出现,而无需为每个 C# 类型编写代码单独。

最佳答案

正如@dbc 在评论中所说,没有一种简单的方法可以让 Json.Net 自动处理您的自定义引用格式。也就是说,您可以使用LINQ-to-JSON (JObjects) 解析 JSON,并借助 JsonConverter和几个字典,解析引用并填充您的类,同时仍然将大部分繁重的工作留给 Json.Net。这是我会采用的方法:

  1. 创建自定义通用 JsonConverter可以解码 [ "FOO", "<key>" ]引用格式并从提供的字典中返回相应的对象。这是转换器的代码:

    public class ReferenceConverter<T> : JsonConverter
    {
    private Dictionary<string, T> ReferenceDict { get; set; }

    public ReferenceConverter(Dictionary<string, T> referenceDict)
    {
    ReferenceDict = referenceDict;
    }

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
    JArray array = JArray.Load(reader);
    if (array.Count == 2 &&
    array[0].Type == JTokenType.String &&
    (string)array[0] == "FOO" &&
    array[1].Type == JTokenType.String)
    {
    string key = (string)array[1];
    T obj;
    if (ReferenceDict.TryGetValue(key, out obj))
    return obj;

    throw new JsonSerializationException("No " + typeof(T).Name + " was found with the key \"" + key + "\".");
    }

    throw new JsonSerializationException("Reference had an invalid format: " + array.ToString());
    }

    public override bool CanWrite
    {
    get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
    throw new NotImplementedException();
    }
    }
  2. 将 JSON 解析为 JObject并建立 Vets 的字典来自 BAR JSON 的一部分。

    JObject data = JObject.Parse(json);

    Dictionary<string, Vet> vets = data["BAR"]
    .Children<JProperty>()
    .Where(jp => jp.Value["vet_id"] != null)
    .ToDictionary(jp => jp.Name, jp => jp.Value.ToObject<Vet>());
  3. 构建字典 Animals来自 BAR JSON 部分,使用 ReferenceConverter<T>和第 2 步中的字典来解析 Vet引用资料。

    JsonSerializer serializer = new JsonSerializer();
    serializer.Converters.Add(new ReferenceConverter<Vet>(vets));

    Dictionary<string, Animal> animals = data["BAR"]
    .Children<JProperty>()
    .Where(jp => jp.Value["animal_id"] != null)
    .ToDictionary(jp => jp.Name, jp => jp.Value.ToObject<Animal>(serializer));
  4. 最后,反序列化 users来自 JSON 的列表,再次使用 ReferenceConverter<T>加上两个字典(现在实际上有两个转换器实例,每个字典一个)来解析所有引用。

    serializer.Converters.Add(new ReferenceConverter<Animal>(animals));
    List<User> users = data["users"].ToObject<List<User>>(serializer);

完整演示在这里:https://dotnetfiddle.net/uUuy7v

关于c# - 使用自定义格式作为引用时,如何使用 Json.NET 通过引用反序列化对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43048335/

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