簡體   English   中英

如何使用DataContractJsonSerializer解析包含混合基本類型的json對象數組?

[英]How to parse a json object array containing mixed primitive types using DataContractJsonSerializer?

如何在C#中使用DataContractJsonSerializer解析下面的JSON對象?

我將需要定義一個類來保存以下JSON數據,其中包括混合類型(字符串和整數)的原語數組的數組:

Body:
    {
      "status": "failure",
      "staticdata": [
        [
          "2013-06-01",
          123
        ],
        [
          "2013-06-02",
          234
        ],
        [
          "2013-06-03",
          345
        ],    
        ...
      ]
    }

我嘗試了以下答案,並試圖通讀DataContractJsonSerializer

DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(RootObject));

object objResponse = jsonSerializer.ReadObject(response);

RootObject jsonResponse = objResponse as RootOject;

foreach (object[] sd in jsonResponse.staticdata)
{
    foreach (object o in sd)
    {
        //Value val = v as Value;
        Value val = (Value)Convert.ChangeType(o, typeof(Value));
            log.Info("date: " + val.date);
            log.Info("crashCount: " + val.longValue);
   }
} 

但是在從對象到值的轉換類型崩潰時,我在這里缺少什么嗎?

值低於等級:

[DataContract]
public class Value
{
    [DataMember(Name = "date")]
    public string date { get; set; }

    [DataMember(Name = "longValue")]
    public long longValue{ get; set; }
}

修改后的代碼讀取值(IgnoreDataMember值),然后可以按以下方式讀取:這是正確的方法嗎?

object objResponse = jsonSerializer.ReadObject(response);

RootObject jsonResponse = objResponse as RootOject;

foreach (Value in jsonResponse.Values)
{
            log.Info("date: " + val.date);
            log.Info("longValue: " + val.longValue);
} 

如果您只想反序列化JSON,則可以使用代碼生成工具(例如http://json2csharp.com/)或將JSON作為類粘貼,並獲得以下數據模型,該數據模型與DataContractJsonSerializer完美DataContractJsonSerializer

public class RootObject
{
    public string status { get; set; }
    public List<List<object>> staticdata { get; set; }
}

object之所以起作用,是因為DataContractJsonSerializer自動識別並序列化已知的原始類型,例如stringint

但是,您可能想要將"staticdata"數組反序列化為此類列表:

public class Value
{
    public string Date { get; set; }
    public int IntValue { get; set; }
}

如果是這樣,您可以使用RootObject類型中的替代屬性來進行轉換:

[DataContract]
public class RootObject
{
    [DataMember]
    public string status { get; set; }

    [DataMember]
    object[][] staticdata
    {
        get
        {
            if (Values == null)
                return null;
            return Values.Select(v => new object[] { v.Date, v.IntValue }).ToArray();
        }
        set
        {
            if (value == null)
                return;
            Values = value.Select(a => new Value 
                { 
                    Date = a.Length < 1 ? null : (string)Convert.ChangeType(a[0], typeof(string), CultureInfo.InvariantCulture),
                    IntValue = a.Length < 2 ? 0 : (int)Convert.ChangeType(a[1], typeof(int), CultureInfo.InvariantCulture) 
                }
                ).ToList();
        }
    }

    [IgnoreDataMember]
    public List<Value> Values { get; set; }
}

更新資料

在您詢問的更新問題中, 但是在從對象到值的轉換類型崩潰時,我在這里缺少什么嗎?

您的問題是您試圖使用Convert.ChangeType()object轉換為Value ,但是此方法僅適用於可以在字符串之間進行轉換的原始數據類型。 文檔

ChangeType是一種通用的轉換方法,它將由值指定的對象轉換為conversionType。 value參數可以是任何類型的對象,conversionType也可以是表示任何基本或自定義類型的Type對象。 為使轉換成功,值必須實現IConvertible接口,因為該方法只是將對一個合適的IConvertible方法的調用包裝起來。

由於您的Value類型未實現此接口,因此轉換失敗。

相反,您應該在嵌套數組中的各個條目上使用Convert.ChangeType 給定您的RootObject看起來像:

public class RootObject
{
    public string status { get; set; }
    public object [][] staticdata { get; set; }
}

你應該做:

using System.Linq;

DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(RootObject));
var jsonResponse = (RootObject)jsonSerializer.ReadObject(response);

var query = jsonResponse.staticdata
    // For each object [] array in the outer array
    .Select(a => new Value
        {
             // Convert the inner array to a Value, using the first element for the date and the second element for the longValueand the second element for the longValue
            date = a.Length < 1 ? null : (string)Convert.ChangeType(a[0], typeof(string), CultureInfo.InvariantCulture),
            longValue = a.Length < 2 ? 0 : (long)Convert.ChangeType(a[1], typeof(long), CultureInfo.InvariantCulture)
        });

foreach (var val in query)
{
    log.Info("date: " + val.date);
    log.Info("crashCount: " + val.longValue);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM