Как проанализировать массив объектов json, содержащий смешанные типы примитивов, используя DataContractJsonSerializer?
Как я могу разобрать объект JSON ниже, используя DataContractJsonSerializer
в C#?
Мне нужно будет определить класс для хранения приведенных ниже данных 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);
}
}
но в converttype от объекта до значения происходит сбой, я что-то здесь упускаю.
Значение ниже класса:
[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);
}
1 ответ
Если вы просто хотите десериализовать свой JSON, вы можете использовать инструмент генерации кода, например http://json2csharp.com/ или Вставить JSON As Classes, и получить следующую модель данных, которая прекрасно работает с DataContractJsonSerializer
:
public class RootObject
{
public string status { get; set; }
public List<List<object>> staticdata { get; set; }
}
object
работает потому что DataContractJsonSerializer
автоматически распознает и сериализует известные примитивные типы, такие как string
а также int
,
Но то, что вы можете захотеть, это десериализовать "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 - это метод преобразования общего назначения, который преобразует объект, указанный в значении, в преобразование типа. Параметр value может быть объектом любого типа, а translationType также может быть объектом 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);
}