在C#中获取我的JSON数据的特定部分

时间:2018-10-17 18:36:33

标签: c# json

我有这个JSON:

{
    "response":
    {
        "data":
        [
            {
                "start":1,
                "subjects":["A"]
            },
            {
                "start":3,
                "subjects":["B"]
            },
            {
                "start":2,
                "subjects":["C"]
            }
        ]
    }
}

并且我只想从对象中获取“主题”数据,其“开始”值应大于1.3,在这种情况下为C。这是最小的吗?有人会碰巧知道这种情况吗?可以使用C#来实现?

2 个答案:

答案 0 :(得分:3)

我想在其他答案上再加上一点点,为主题提供更多的启示。

JSON- JavaScript对象符号 -只是一种“在线”移动数据的方式。在.NET内部,尽管您可能会通俗地引用这样的数据结构,但您实际上不应将您的对象视为JSON。

话虽如此,什么是JSON“ .side” .NET?是你的电话。例如,您可以将其视为string,但是您将很难执行此操作以根据某些参数/规则查找特定节点。

由于JSON是树状结构,因此您可以构建数据结构或使用Web上的许多可用结构。如果您通常学习该语言和编程的知识,那将是一件好事,而如果您是专业地这样做,那将是一件不好的事,因为您可能会重新发明轮子。而且解析 JSON并非易事(再次,很好的练习)。

那么,最省时的方法是?您有两种选择:

  1. 使用dynamic对象表示您的JSON数据。动态是对.NET的“扩展”(实际上是CLR的扩展,称为DLR),它使您可以创建没有类的对象(可以将它们视为“无类型”,或者更好的是,使用鸭子打字)。

  2. 使用您定义的类型化结构来保存数据。这是规范的,面向对象的.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);

如果使用这种方法,则不需要类上的注释(所有DataMemberDataContract),从而使代码更简洁。与DataContractJsonSerializer相比,我非常喜欢使用这种方法,但这是您的要求。


我已经讨论了很多有关对象的序列化和反序列化的问题,但是您的问题是“如何找到某个节点?”。以上所有讨论仅是前提条件。

同样,还有几种实现所需目标的方法:

  1. @YouneS答案。这非常简单,可以满足您的需求。

  2. 使用上面的第二种方法,然后使用键入的对象获得所需的内容。例如:

    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. 您可以使用Newtonsoft的一项功能,该功能可以直接找到所需的节点。请参阅the documentation。警告,对于简单的情况,它有点高级,可能会过大。

答案 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;
}