gpt4 book ai didi

c# - 如何使用自定义 JsonConverter 仅反序列化 Json.NET 中的子对象?

转载 作者:太空宇宙 更新时间:2023-11-03 12:21:25 25 4
gpt4 key购买 nike

我想从网络响应中反序列化 JSON。这是一个典型的回应:

{
"response": {
"garbage": 0,
"details": [
{
"id": "123456789"
}
]
}
}

但是,这种格式是不可取的。理想情况下,响应只是

{
"id": "123456789"
}

这样它就可以被反序列化为一个对象

public class Details {
[JsonProperty("id")]
public ulong Id { get; set; }
}

由于我无法控制服务器(它是一个公共(public) API),我打算修改反序列化过程以获得我想要的格式。


我尝试使用自定义 JsonConverter 来完成此操作。我的想法是跳过标记,直到我找到反序列化到 Details 所需的起点。但是,我不确定在反序列化过程中应该在哪里使用它。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Newtonsoft.Json;

namespace ConsoleApp2 {
class Program {
static void Main(string[] args) {
// Simulating a stream from WebResponse.
const string json = "{"response":{"garbage":0,"details":[{"id":"123456789"}]}}";
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(json);
Stream stream = new MemoryStream(bytes);

Details details = Deserialise<Details>(stream);

Console.WriteLine($"ID: {details.Id}");
Console.Read();
}

public static T Deserialise<T>(Stream stream) where T : class {
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) {
JsonSerializerSettings settings = new JsonSerializerSettings {
MissingMemberHandling = MissingMemberHandling.Ignore,
DateParseHandling = DateParseHandling.None
};

settings.Converters.Add(new DetailConverter());
return JsonSerializer.Create(settings).Deserialize(reader, typeof(T)) as T;
}
}
}

public class Details {
[JsonProperty("id")]
public ulong Id { get; set; }
}

public class DetailConverter : JsonConverter {
public override void WriteJson(JsonWriter writer,
object value,
JsonSerializer serializer) {
throw new NotImplementedException();
}

public override object ReadJson(JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer) {
if (reader.Depth == 0) {
while (!(reader.Path.Equals("response.details[0]", StringComparison.OrdinalIgnoreCase) && reader.TokenType == JsonToken.StartObject)) {
reader.Read();
}

try {
return serializer.Deserialize(reader, objectType);
} finally {
reader.Read(); // EndArray - details
reader.Read(); // EndObject - response
reader.Read(); // EndObject - root
}
}

return serializer.Deserialize(reader, objectType);
}

public override bool CanWrite => false;
public override bool CanConvert(Type objectType) => true;
}
}

就目前情况而言,堆栈溢出是因为 DetailConverter.ReadJson() 被重复用于同一个对象并且它永远不会被反序列化。我认为这是因为我通过 JsonSerializerSettingsDetailConverter 设置为“全局”转换器。我认为问题在于何时以及如何使用我的转换器,而不是其内部工作原理。


我有一个类似的 DetailConverter 可以用于以下结构。但是,尽管 details 中的数组已被删除,但由于嵌套和未使用的属性,它仍然不受欢迎。

public class Root {
[JsonProperty("response")]
public Response Response { get; set; }
}

public class Response {
[JsonProperty("details")]
[JsonConverter(typeof(DetailConverter))]
public Details Details { get; set; }

[JsonProperty("garbage")]
public uint Garbage { get; set; }
}

public class Details {
[JsonProperty("id")]
public ulong Id { get; set; }
}

我认为将转换器扩展到整个 JSON 而不仅仅是一个属性会很简单。我哪里出错了?

最佳答案

Linq to JSON 适合您吗?

using System;
using Newtonsoft.Json.Linq;

public class Program
{
public static void Main()
{
var json = "{'response':{'garbage':0,'details':[{'id':'123456789'}]}}";
var obj = JObject.Parse(json);
var details = obj["response"]["details"];

Console.WriteLine(details);
}
}

关于c# - 如何使用自定义 JsonConverter 仅反序列化 Json.NET 中的子对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46987468/

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