更新反序列化JSON对象的属性(没有定义的沙漠类型)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了更新反序列化JSON对象的属性(没有定义的沙漠类型)相关的知识,希望对你有一定的参考价值。
我将一些JSON作为字符串并将其存储为:
private static List<object> history = new List<object>();
var data = JsonConvert.DeserializeObject(parsedData);
history.Add(data);
JSON数据看起来像这样:
{ id: 12, data: 'my data' }
我想添加另一个迭代history
列表的方法,通过其ID找到一个项目并更新它。
访问像这样的对象的属性的最佳方法是什么?
如果传入的JSON字符串始终具有相同的字段,则可以将其序列化为已定义的类/类型。
public class JsonHistory
{
public int id { get; set; }
public string data { get; set; }
}
List<JsonHistory> history = new List<JsonHistory>();
var histData= JsonConvert.DeserializeObject<JsonHistory>(parsedData);
history.Add(histData);
然后,您还可以使用linq查找您要查找的任何匹配项:
var matches = history.Where(x => x.id == 10).Select(x => x.data);
您可以使用dynamic
而不是object
,因为它更容易使用属性而不是object
List<dynamic> history = new List<dynamic>();
string parsedData = "{ id: 12, data: 'my data' }";
var data = JsonConvert.DeserializeObject<dynamic>(parsedData);
history.Add(data);
history.Add(data);
foreach (var o in history)
{
o.id = 13;
}
另外,我强烈建议您创建一个类并将其用作已知类型。这将给你智能感知,你肯定会需要更进一步。
JSON.NET documentation有以下方法,我也建议使用:
首先 - 反序列化为合理类型(匿名很好)
var json = "{id: 12, data: 'my data'}";
var definition = new { Id = 0, Data = "" }
var deserialised = JsonConvert.DeserializeAnonymousType(json, definition);
第二 - 你有第一个项目,所以你可以“欺骗”编译器让你在列表中使用匿名类型:
var history = (new[] { deserialised }).ToList();
然后,您可以将任何其他反序列化的实例推送到该列表中。
现在你可以进行过滤了:
var itemImLookingFor = history.SingleOrDefault(x => x.Id == 10);
一旦你得到了这个项目,你就可以更新它:
itemImLookingFor.Data = itemImLookingFor.Data.ToUpperCase()
我建议阅读this,因为它解释了使用dynamic
关键字时固有的一些缺点;这不是一件坏事,它只是有它的位置。
对于这种情况,JSON.NET为您提供了所需的所有工具,可以反序列化为您自己定义的类型(例如,编写一个镜像JSON的类,或者像我在这里完成的匿名类型)。
通常的方法是反序列化为自定义类或反序列化为JObject,这将允许您迭代其属性,如使用反射。两者都需要大量打字。
但是你可以使用一个聪明的小技巧,并获得强大类型的所有好处,而无需编写类。
使用匿名鸭子类型
将此方法添加到您的库中:
static public T JsonDeserialize<T>(string input, T template)
{
return JsonConvert.DeserializeObject<T>(input);
}
一旦你有了这个,你可以通过提供一个示例实例来使用它来点击JSON(即让编译器推断出一个匿名类型)。这允许您使用匿名类型而不是键入自定义类。
例如,要获取ID为12的行,您可以执行以下操作:
using System;
using System.Linq;
using Newtonsoft.Json;
public class Program
{
static public T JsonDeserialize<T>(string input, T example)
{
return JsonConvert.DeserializeObject<T>(input);
}
public static void Main()
{
//Sample data with two records
const string input = @"[ { 'id' : 12, 'data' : 'MyData' }, { 'id' : 13, 'data' : 'Another record' } ]";
//Create an example instance so the compiler can use its anonymous type
var example = new []
{
new { id = default(int), data = default(string) }
};
//Pass the example as argument 2 so that the compiler can infer T. The argument itself isn't used for anything.
var list = JsonDeserialize(input, example);
//Now we have a strongly-typed list, without having to write a class
//We can use LINQ or anything else that needs a strong type
foreach ( var o in list.Where( a => a.id == 12) )
{
Console.WriteLine(o.id);
Console.WriteLine(o.data); //Intellisense works here
}
}
}
输出:
12
MyData
Working example on DotNetFiddle。
以上是关于更新反序列化JSON对象的属性(没有定义的沙漠类型)的主要内容,如果未能解决你的问题,请参考以下文章