在C#中解析此JSON对象的正确方法是什么?

时间:2016-06-12 04:37:37

标签: c# json linq json.net

这是我从GET请求收到的JSON对象:

{
"data": {
    "valve_maker": [],
    "water_volume": [
        "15L",
        "20L",
        "..."
    ],
    "cylinder_manufacturer": [
        "Tianhai"
    ],
    "qc_stamp": [
        "TS"
    ],
    "reference_standard": [
        "GB 5099"
    ],
    "production_licence": [
        "TS2210752-2016"
    ],
    "valve_production_licence": [
        "TSF210030"
    ],
    "rate_of_residual_deformation": {
        "1": "<3%",
        "2": "<10%"
    },
    "material_number": {
        "1": "30CrMo",
        "2": "34CrMo4",
        "3": "..."
    },
    "heat_treatment": {
        "1": "...",
        "2": "..."
    },
    "drawing_number": {
        "1": "...",
        "2": "..."
    },
    "cylinder_thickness": []
}

现在,我能够使用更简单的结构解析JSON对象,如:

{
"data": [
    {
        "gas_id": "ID of the gas",
        "gas_name": "Gas name"
    }
]

使用类似的东西:

private void jsonparsegas(string res)
    {
        JObject par = JObject.Parse(res);
        foreach (JToken data in par["data"].Children())
        {
            string id = data["gas_id"].ToString();
            string name = data["gas_name"].ToString();
            if (this.cmbCylType.Items.Contains(name) == false)
            {
                this.cmbCylType.Items.Add(name);
            }
        }
    }

当我尝试将相同的东西应用于更复杂的JSON对象时,我收到错误:

private void jsonparsecoc(string res)
    {
        //JObject par = JObject.Parse(res);
        var jObj = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(res);
        foreach (var child in jObj["data"].Children())   
        {

            string vMaker = child["valve_maker"].ToString(); //error thrown here right away
            string wVolume = child["water_volume"].ToString();
            string cMan = child["cylinder_manufacturer"].ToString();
            string QC = child["qc_stamp"].ToString();
            string rStandard = child["reference_standard"].ToString();
            string pLicence = child["production_licence"].ToString();
            string VPL = child["valve_production_licence"].ToString();
            string rrd = child["rate_of_residual_deformation"].ToString();
            string mNum = child["material_number"].ToString();
            string hTreatment = child["heat_treatment"].ToString();
            string dNum = child["drawing_number"].ToString();
            string cThick = child["cylinder_thickness"].ToString();

        }
  

无法访问Newtonsoft.Json.Linq.JProperty

上的子值

我尝试过在StackOverflow上找到的一些不同的东西,但我真的不明白对象的反序列化是如何工作的。更简单的解析工作得很好,并允许我将从GET请求收到的所有“gas_name”添加到组合框中。 “data”的第一个“valve_maker”子元素的格式似乎与更相似的JSON对象中的“gas_id”或“gas_name”具有相同的结构,但这是我立即收到错误的地方。如果我不得不猜测错误的原因,我会说它与使用

之间的区别有关
  

“valve_maker”:[]

并使用

  

“gas_id”:“气体的ID”

在对象中。另外我注意到“数据”后面跟着更简单的[]括号,而{}则是更复杂的括号。

如果有人可以链接到一些好的阅读材料,或者提供一个解决方案的正确解释/正在发生什么,我真的很感激。

3 个答案:

答案 0 :(得分:1)

这部分是您遇到的问题的关键:

  

在对象中。另外我注意到“数据”后面跟着更简单的[]括号,而{}则是更复杂的括号。

JSON

  • []括号括起一个数组
  • {}括号括起一个对象

在两个代码示例中,您通过使用par["data"].Children()循环结果来挖掘对象。为了与JSON模型保持一致,JSON.NET为解析objectsarrays的子项定义了不同的行为。对象的子节点是它的属性,数组的子节点是它的项。

在您的代码中,jsonparsegas的输入是一个包含2个属性的简单对象数组,其中jsonparsecoc的输入是具有许多属性的单个复杂对象。

jsonparsegas中,Children()调用会为您提供所有简单气体对象的数组。循环遍历这些对象并为每个对象提取“gas_id”和“gas_name”的值。在您的示例数据中,恰好只有一个气体对象,因此您的代码只执行一次。

jsonparsecoc中,Children()调用实际上为复杂对象的属性提供了属性值,因为结果是对象而不是数组。因此,当您遍历此结果时,您无法访问“valve_maker”之类的内容,因为它们是在复杂对象上定义的,并且您已经步入valve_maker的值然后执行。

解决方案很简单。 不要遍历jsonparsecoc中的属性。而不是foreach(var child in jObj["data"].Children()),你需要像var child = jObj["data"];这样的东西。这将为您提供实际包含您尝试访问的每个属性的对象的引用。

答案 1 :(得分:1)

@smartcaveman很好地解释了代码出了什么问题。但是,如果您为此定义强类型类,则可能会发现您的数据更容易处理:

class RootObject
{
    public Data Data { get; set; }
}

class Data
{
    [JsonProperty("valve_maker")]
    public List<string> ValveMaker { get; set; }

    [JsonProperty("water_volume")]
    public List<string> WaterVolume { get; set; }

    [JsonProperty("cylinder_manufacturer")]
    public List<string> CylinderManufacturer { get; set; }

    [JsonProperty("qc_stamp")]
    public List<string> QCStamp { get; set; }

    [JsonProperty("reference_standard")]
    public List<string> ReferenceStandard { get; set; }

    [JsonProperty("production_licence")]
    public List<string> ProductionLicense { get; set; }

    [JsonProperty("valve_production_licence")]
    public List<string> ValveProductionLicense { get; set; }

    [JsonProperty("rate_of_residual_deformation")]
    public Dictionary<string, string> RateOfResidualDeformation { get; set; }

    [JsonProperty("material_number")]
    public Dictionary<string, string> MaterialNumber { get; set; }

    [JsonProperty("heat_treatment")]
    public Dictionary<string, string> HeatTreatment { get; set; }

    [JsonProperty("drawing_number")]
    public Dictionary<string, string> DrawingNumber { get; set; }

    [JsonProperty("cylinder_thickness")]
    public List<string> CylinderThickness { get; set; }
}

您可以将JSON反序列化到您的类中,如下所示:

RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);

在这里演示:https://dotnetfiddle.net/p0D7ze

答案 2 :(得分:0)

    public class Test{
    public Data data{get;set;}
}

public class Data{
     public List<string> Value_maker{get;set;}
    public List<String> Water_Volume{get;set;}
    public List<String> cylinder_manufacturer{get;set;}
}

创建类结构,然后使用反序列化 Jsonconvert.DeserializeObject(JsonString) 它将json转换为适当的对象,请记住结构应该是正确的,属性名称应该与您的json属性相同 希望它会帮助你