C# 使用JsonConverter JSON.net将JSON反序列化到对象列表
我想将JSON反序列化为对象列表,JSON的结构如下C# 使用JsonConverter JSON.net将JSON反序列化到对象列表,c#,json.net,C#,Json.net,我想将JSON反序列化为对象列表,JSON的结构如下 { "metadata":{ I don't care about metadata }, "results": [ { object that I really want }, { object that I really want }, { object that I really want } ... ] } public class Bo
{
"metadata":{ I don't care about metadata },
"results": [
{ object that I really want },
{ object that I really want },
{ object that I really want }
...
]
}
public class BoringTypeConverter : JsonConverter<List<BoringType>>
{
public override bool CanRead => true;
public override List<BoringType> ReadJson(JsonReader reader, Type objectType, List<BoringType> existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
List<BoringType> boringTypes = new List<BoringType>();
var jObject = JObject.Load(reader);
JArray results = (JArray)jObject["results"];
foreach (var bor in results)
{
var boring = new BoringType();
var region = (string)bor["region"];
var source = (string)bor["source"];
JToken source = (string)bor["source"];
JToken target = (string)bor["target"];
boring.Region = region;
boring.Source = source;
boring.Source = (string)source["id"];
boring.Target = (string)target["id"];
boringTypes.Add(boring);
}
return boringTypes;
}
public override void WriteJson(JsonWriter writer, List<BoringType> value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
我只想获取结果
节点中的对象列表,因为有一些属性我想自己对其进行反序列化,所以我使用来自的实现来实现JsonConverter
,他创建了名为JsonCreationConverter
的派生泛型类JsonCreationConverter
,该类具有protect abstractCreate
方法,该方法实际上反序列化了JSON,而JSON又被JsonConverter
的ReadJson
调用
我的派生类的签名及其Create
签名如下
public class BoringTypeConverter: JsonCreationConverter<List<BoringType>>
{
protected override List<BoringType> Create(Type objectType, JObject jObject)
{
List<BoringType> boringTypes = new List<BoringType>();
JArray results = (JArray)jObject["results"];
// deserialize logic
...
return boringTypes;
}
}
公共类BoringTypeConverter:JsonCreationConverter
{
受保护的覆盖列表创建(类型objectType,JObject JObject)
{
列表类型=新列表();
JArray结果=(JArray)jObject[“结果”];
//反序列化逻辑
...
返回钻孔类型;
}
}
我就是这样用的
JsonConvert.DeserializeObject<List<BoringType>>(jsonString, new BoringTypeConverter());
JsonConvert.DeserializeObject(jsonString,new BoringTypeConverter());
当我调试测试时,我发现Create
方法成功地将JSON反序列化为List
,但我一点击serializer.Populate(jObjectReader,target)
就出现了错误无法将JSON对象填充到类型“System.Collections.Generic.List1[BoringType]”。路径“元数据”,第2行,位置15。
所以我想知道这就是问题所在?Create
方法没有对metadata
字段执行任何操作,那么为什么它会抱怨元数据
?我创建了一个简单的示例,说明如何执行此操作:
public static class JsonBase<T> where T: BaseData<T>
{
public static List<T> ReturnResultsList(string json)
{
var returnData = JsonConvert.DeserializeObject<BaseData<T>>(json);
return returnData.results;
}
public static string ReturnMetaData(string json)
{
var returnData = JsonConvert.DeserializeObject<BaseData<T>>(json);
return returnData.metadata;
}
}
公共静态类JsonBase,其中T:BaseData
{
公共静态列表ReturnResultsList(字符串json)
{
var returnData=JsonConvert.DeserializeObject(json);
返回数据。返回结果;
}
公共静态字符串返回元数据(字符串json)
{
var returnData=JsonConvert.DeserializeObject(json);
返回returnData.metadata;
}
}
public class BaseData<T> where T: class
{
public string metadata { get; set; }
public List<T> results { get; set; }
}
公共类基本数据,其中T:class
{
公共字符串元数据{get;set;}
公共列表结果{get;set;}
}
public class SomeObjectTHatUwant:BaseData<SomeObjectTHatUwant>
{
public string category { get; set; }/// property for my case
public string quantity { get; set; }
}
公共类SomeObjectTHatUwant:BaseData
{
我的案例的公共字符串类别{get;set;}///属性
公共字符串数量{get;set;}
}
string url = "http://readabook.16mb.com/api/allcategory";///this link return an json
List<SomeObjectTHatUwant> Response = new List<SomeObjectTHatUwant>();///the data you want
private async Task LoadDataAsync(string uri)
{
string responseJsonString = null;
using (var httpClient = new WebClient())
{
try
{
responseJsonString = httpClient.DownloadString(uri);
Response = JsonBase<SomeObjectTHatUwant>.ReturnResultsList(responseJsonString);
}
catch (Exception)
{
throw;
}
}
}
stringurl=”http://readabook.16mb.com/api/allcategory";///此链接返回一个json
列表响应=新列表()///你想要的数据
专用异步任务LoadDataAsync(字符串uri)
{
字符串响应JSONSTRING=null;
使用(var httpClient=new WebClient())
{
尝试
{
responseJsonString=httpClient.DownloadString(uri);
Response=JsonBase.ReturnResultsList(responseJsonString);
}
捕获(例外)
{
投掷;
}
}
}
LoadDataAsync(url)代码>此方法在案例响应字段中初始化,
这是我们想要的一些对象的列表
希望这有帮助。正如@dbc指出的那样,这个问题实际上是关于如何告诉
JsonConvert.DeserializeObject
它应该反序列化到哪种类型的对象
所以,我实际做的是反序列化对象,然后我告诉JsonConvert
将JSON放入我的BoringType
字段中,该字段不包含元数据。这就是为什么我得到了一个错误,说它不能将JSON放入没有相应字段的类中
事实证明,编写定制JsonConverter非常简单(一旦您了解了Linq的JSON)。
我的转换器看起来像这样
{
"metadata":{ I don't care about metadata },
"results": [
{ object that I really want },
{ object that I really want },
{ object that I really want }
...
]
}
public class BoringTypeConverter : JsonConverter<List<BoringType>>
{
public override bool CanRead => true;
public override List<BoringType> ReadJson(JsonReader reader, Type objectType, List<BoringType> existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
List<BoringType> boringTypes = new List<BoringType>();
var jObject = JObject.Load(reader);
JArray results = (JArray)jObject["results"];
foreach (var bor in results)
{
var boring = new BoringType();
var region = (string)bor["region"];
var source = (string)bor["source"];
JToken source = (string)bor["source"];
JToken target = (string)bor["target"];
boring.Region = region;
boring.Source = source;
boring.Source = (string)source["id"];
boring.Target = (string)target["id"];
boringTypes.Add(boring);
}
return boringTypes;
}
public override void WriteJson(JsonWriter writer, List<BoringType> value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
公共类BoringTypeConverter:JsonConverter
{
public override bool CanRead=>true;
public override List ReadJson(JsonReader读取器、类型objectType、列表existingValue、bool hasExistingValue、JsonSerializer序列化程序)
{
if(reader.TokenType==JsonToken.Null)
返回null;
列表类型=新列表();
var jObject=jObject.Load(读卡器);
JArray结果=(JArray)jObject[“结果”];
foreach(结果中的var bor)
{
var钻孔=新钻孔类型();
变量区域=(字符串)bor[“区域”];
var source=(字符串)bor[“source”];
JToken source=(字符串)bor[“source”];
JToken target=(字符串)bor[“target”];
区域=区域;
无聊。来源=来源;
Source=(字符串)Source[“id”];
目标=(字符串)目标[“id”];
钻孔类型。添加(钻孔);
}
返回钻孔类型;
}
公共重写void WriteJson(JsonWriter编写器、列表值、JsonSerializer序列化器)
{
抛出新的NotImplementedException();
}
}
您的数据模型实际上是多态的吗?描述如何反序列化多态对象列表中的项。这在这里适用吗?你能提供一份吗?@dbc不,不是。谢谢你指出我,我没有仔细阅读这个问题,所以我认为答案是关于如何使用JsonConverter的,现在我明白我在做什么了。下次我将尝试改进这个有问题的例子。我认为它可以更优雅。谢谢你们的回答,我认为这是一个反序列化JSON的好方法,JSON以相同的模式出现(元数据、结果)。然而,事实并非如此