I want to know if it is possible to deserialize a JSON object that could either be an object or an array.
我想知道是否可以反序列化可能是对象或数组的JSON对象。
Similar to this question: Jackson deserialize object or array
与此问题类似:杰克逊反序列化对象或数组
But using JSON.Net.
但是使用JSON.Net。
Example
例
{
"response": {
"status":"success",
// Could be either a single object or an array of objects.
"data": {
"prop":"value"
}
// OR
"data": [
{"prop":"value"},
{"prop":"value"}
]
}
}
3 个解决方案
#1
2
You can change the property type for "data" in your model to dynamic or an object and check if it is an array on run-time.
您可以将模型中“data”的属性类型更改为dynamic或object,并在运行时检查它是否为数组。
Here's an example:
这是一个例子:
public class Response
{
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("data")]
public dynamic Data { get; set; }
}
var response = JsonConvert.DeserializeJson<Response>(json);
.
.
.
Type responseDataType = response.Data.GetType();
if(responseDataType.IsArray) {
// It's an array, what to do?
}
else {
// Not an array, what's next?
}
#2
3
An alternative would be to write our JsonConverter
and use it for deserializing so we can work with static types after conversion.
另一种方法是编写我们的JsonConverter并将其用于反序列化,以便我们可以在转换后使用静态类型。
class JsonDataConverter : JsonConverter
{
public override bool CanWrite { get { return false; } }
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Data);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var token = JToken.ReadFrom(reader);
if (token is JArray)
return new Data(token.Select(t => t["prop"].ToString()));
if (token is JObject)
return new Data(new[] { token["prop"].ToString() });
throw new NotSupportedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
[JsonConverter(typeof(JsonDataConverter))]
class Data:List<string>
{
public Data() : base() { }
public Data(IEnumerable<string> data) : base(data) { }
}
class Response
{
public string Status { get; set; }
public Data Data { get; set; }
}
and an example:
一个例子:
class Program
{
static void Main(string[] args)
{
var inputObj = @"{
'response': {
'status':'success',
// Could be either a single object or an array of objects.
'data': { 'prop':'value'}
}
}";
var inputArray = @"{
'response': {
'status':'success',
// Could be either a single object or an array of objects.
'data':[
{ 'prop':'value'},
{ 'prop':'value'}
]
}
}";
var obj = JsonConvert.DeserializeAnonymousType(inputObj, new { Response = new Response() });
foreach(var prop in obj.Response.Data)
Console.WriteLine(prop);
var arr = JsonConvert.DeserializeAnonymousType(inputArray, new { Response = new Response() });
foreach (var prop in arr.Response.Data)
Console.WriteLine(prop);
}
}
#3
2
I think this solves your problem
我认为这解决了你的问题
string jsonString= "your json string";
var token = JToken.Parse(jsonString);
if (token is JArray)
{
IEnumerable<Car> cars= token.ToObject<List<Car>>();
}
else if (token is JObject)
{
Car car= token.ToObject<Car>();
}
#1
2
You can change the property type for "data" in your model to dynamic or an object and check if it is an array on run-time.
您可以将模型中“data”的属性类型更改为dynamic或object,并在运行时检查它是否为数组。
Here's an example:
这是一个例子:
public class Response
{
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("data")]
public dynamic Data { get; set; }
}
var response = JsonConvert.DeserializeJson<Response>(json);
.
.
.
Type responseDataType = response.Data.GetType();
if(responseDataType.IsArray) {
// It's an array, what to do?
}
else {
// Not an array, what's next?
}
#2
3
An alternative would be to write our JsonConverter
and use it for deserializing so we can work with static types after conversion.
另一种方法是编写我们的JsonConverter并将其用于反序列化,以便我们可以在转换后使用静态类型。
class JsonDataConverter : JsonConverter
{
public override bool CanWrite { get { return false; } }
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Data);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var token = JToken.ReadFrom(reader);
if (token is JArray)
return new Data(token.Select(t => t["prop"].ToString()));
if (token is JObject)
return new Data(new[] { token["prop"].ToString() });
throw new NotSupportedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
[JsonConverter(typeof(JsonDataConverter))]
class Data:List<string>
{
public Data() : base() { }
public Data(IEnumerable<string> data) : base(data) { }
}
class Response
{
public string Status { get; set; }
public Data Data { get; set; }
}
and an example:
一个例子:
class Program
{
static void Main(string[] args)
{
var inputObj = @"{
'response': {
'status':'success',
// Could be either a single object or an array of objects.
'data': { 'prop':'value'}
}
}";
var inputArray = @"{
'response': {
'status':'success',
// Could be either a single object or an array of objects.
'data':[
{ 'prop':'value'},
{ 'prop':'value'}
]
}
}";
var obj = JsonConvert.DeserializeAnonymousType(inputObj, new { Response = new Response() });
foreach(var prop in obj.Response.Data)
Console.WriteLine(prop);
var arr = JsonConvert.DeserializeAnonymousType(inputArray, new { Response = new Response() });
foreach (var prop in arr.Response.Data)
Console.WriteLine(prop);
}
}
#3
2
I think this solves your problem
我认为这解决了你的问题
string jsonString= "your json string";
var token = JToken.Parse(jsonString);
if (token is JArray)
{
IEnumerable<Car> cars= token.ToObject<List<Car>>();
}
else if (token is JObject)
{
Car car= token.ToObject<Car>();
}