2016-06-12 73 views
1

這是我從一個GET請求接收的JSON對象:在C#中解析這個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(); 

     } 

Cannot access child value on Newtonsoft.Json.Linq.JProperty

我已經嘗試了一些不同的東西,我在計算器上找到,但我真的不理解對象的反序列化是如何工作的。更簡單的解析工作很好,並允許我將從GET請求收到的所有「gas_name」添加到組合框。 「數據」的第一個「valve_maker」孩子的格式似乎與更類似的JSON對象中的「gas_id」或「gas_name」具有相同的結構,但這是我立即收到錯誤的地方。如果我在爲錯誤的原因猜測,我會說這有什麼用

"valve_maker": []

,並使用

"gas_id": "ID of the gas"

中的對象

之間做的差。另外我注意到「數據」後面跟着更簡單的括號,而更復雜的是{}。

如果任何人都可以鏈接到一些很好的閱讀材料,或提供一個解決方案/發生了什麼的好解釋,我真的很感激。

+1

{}是c#中的一個類,[]是一個數組,一個集合,一個列表,[{},{},{}]是一個類的數組,{'array':[]}是一個具有數組屬性的類.... –

+2

通常我會說使用http://json2csharp.com/產生一個類結構,然後我們e通用'DeserializeObject <>()'簽名來創建一個強類型的結構化結果。但是,您的示例輸入在其中包含一些數字作爲屬性的名稱,這在C#對象中是不允許的。這些類型的對象是否具有固定的結構,或者它們是否具有任意數量的屬性? – StriplingWarrior

+1

@StriplingWarrior您可以使用[一個屬性](http://www.newtonsoft.com/json/help/html/serializationattributes.htm)來覆蓋名稱。 –

回答

1

這部分是關鍵,你遇到的問題:

in the objects. also I notice "data" is followed by [] brackets in the simpler one, and {} in the more complicated one.

JSON

  • []括起來的數組
  • {}括起來的對象

在這兩個代碼示例中,y通過使用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"];。這將爲您提供對象的參考,該對象實際上包含您嘗試訪問的每個屬性。

+0

哈哈謝謝,這個幫了很多。我忽略了這樣一個事實,即更簡單的一個是我通過循環的許多事例之一,而複雜的事物只是一件大事,並且不需要循環。 – Lodestone6

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 property 希望它會幫助你

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

相關問題