我有这个JSON:
{
"response":
{
"data":
[
{
"start":1,
"subjects":["A"]
},
{
"start":3,
"subjects":["B"]
},
{
"start":2,
"subjects":["C"]
}
]
}
}
并且我只想从对象中获取“主题”数据,其“开始”值应大于1.3,在这种情况下为C。这是最小的吗?有人会碰巧知道这种情况吗?可以使用C#来实现?
答案 0 :(得分:3)
我想在其他答案上再加上一点点,为主题提供更多的启示。
JSON- JavaScript对象符号 -只是一种“在线”移动数据的方式。在.NET内部,尽管您可能会通俗地引用这样的数据结构,但您实际上不应将您的对象视为JSON。
话虽如此,什么是JSON“ .side” .NET?是你的电话。例如,您可以将其视为string
,但是您将很难执行此操作以根据某些参数/规则查找特定节点。
由于JSON是树状结构,因此您可以构建数据结构或使用Web上的许多可用结构。如果您通常学习该语言和编程的知识,那将是一件好事,而如果您是专业地这样做,那将是一件不好的事,因为您可能会重新发明轮子。而且解析 JSON并非易事(再次,很好的练习)。
那么,最省时的方法是?您有两种选择:
使用dynamic
对象表示您的JSON数据。动态是对.NET的“扩展”(实际上是CLR的扩展,称为DLR),它使您可以创建没有类的对象(可以将它们视为“无类型”,或者更好的是,使用鸭子打字)。
使用您定义的类型化结构来保存数据。这是规范的,面向对象的.NET方法,但是在声明类和键入所有内容时需要权衡取舍,这在时间上是昂贵的。结果是您可以获得更好的智能感知,性能(DLR对象比传统对象慢)和更安全的代码。
要采用第一种方法,可以参考@YouneS答案。您需要向项目Newtonsoft.Json
(一个nuget)中添加一个依赖项,并调用反序列化以将JSON字符串转换为动态对象。从他的回答中可以看出,可以像使用JavaScript语言那样访问该对象中的属性。但是您还将认识到您没有智能感知,将允许使用myObj.unexistentField = "asd"
之类的东西。这就是动态类型化对象的本质。
第二种方法是声明所有类型。同样,这很耗时,在许多情况下,您宁愿不这样做。请参阅Microsoft Docs以获取更多见识。
您应该首先创建数据合同,如下所示(请原谅我的错字,我不会编译代码)。
[DataContract]
class DataItem
{
[DataMember]
public string Start { get; set; }
[DataMember]
public string[] Subjects { get; set; }
}
[DataContract]
class ResponseItem
{
[DataMember]
public DateItem[] Data { get; set; }
}
[DataContract]
class ResponseContract
{
[DataMember]
public ResponseItem Response { get; set; }
}
一旦声明了所有这些数据结构,就将json反序列化为它:
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
var deserializer = new DataContractJsonSerializer(typeof(ResponseContract));
return (T)deserializer.ReadObject(ms);
}
上面的代码可能看起来有些复杂,但是遵循一些.NET / BCL标准。 DataContractJsonSerializer
仅适用于流,因此您需要打开一个包含字符串的流。因此,您将使用json字符串中的所有字节创建一个内存流。
您还可以使用Newtonsoft来做到这一点,这虽然简单得多,但是当然仍然需要额外的依赖项:
DataContract contract = JsonConvert.DeserializeObject<DataContract>(output);
如果使用这种方法,则不需要类上的注释(所有DataMember
和DataContract
),从而使代码更简洁。与DataContractJsonSerializer相比,我非常喜欢使用这种方法,但这是您的要求。
我已经讨论了很多有关对象的序列化和反序列化的问题,但是您的问题是“如何找到某个节点?”。以上所有讨论仅是前提条件。
同样,还有几种实现所需目标的方法:
@YouneS答案。这非常简单,可以满足您的需求。
使用上面的第二种方法,然后使用键入的对象获得所需的内容。例如:
var contract = JsonConvert.DeserializeObject<DataContract>(output);
var query = from dataItem in contract.Response.Data
where dataItem.Start > 1.3
order by dataItem.Start;
var item = query.FirstOrNull();
这将返回第一个项目,由于已订购,因此应为最小项目。请记住要测试结果是否为空。
答案 1 :(得分:1)
您可以使其与以下代码类似:
// Dynamic object that will hold your Deserialized json string
dynamic myObj = JsonConvert.DeserializeObject<dynamic>(YOUR-JSON-STRING);
// Will hold the value you are looking for
string[] mySubjectValue = "";
// Looking for your subject value
foreach(var o in myObj.response.data) {
if(o.start > 1.3)
mySubjectValue = o.subjects;
}