2014-12-24 3 views
1

Я хочу десериализовать json, который возвращает разные данные для разных параметров. В основном я получаю:Deserialise dynamic json types

{"posts": [{ "id" : 1, "name":"post1" },{ "id" : 1, "name":"post1" }]} 

Но иногда данные возвращаемые

{"posts": false} 

Я десериализации это как следующий класс

public class GetReaderResponse 
{ 
    public IEnumerable<ReaderPost> posts {get; set;} 
} 

public class ReaderPost 
{ 
    public int id {get; set;} 
    public string name{get; set;} 
} 

Я использую C#, но json.net не в состоянии сделать это правильно.

Newtonsoft.Json.JsonConvert.DeserializeObject<GetReaderResponse>(dataString); 

ответ

2

Вы можете построить собственный конвертер, но простой способ справиться с этим было бы написать обработчик ошибок, который обнаруживает ошибки с posts свойством:

var settings = new JsonSerializerSettings(); 

settings.Error += (sender, args) => 
{ 
    if (string.Equals("posts", args.ErrorContext.Path, StringComparison.OrdinalIgnoreCase)) 
    { 
     var currentObject = args.CurrentObject as GetReaderResponse; 

     currentObject.posts = Enumerable.Empty<ReaderPost>(); 

     args.ErrorContext.Handled = true; 
    } 
}; 

GetReaderResponse resp = 
    JsonConvert.DeserializeObject<GetReaderResponse>(json, settings); 

Это устанавливает posts в Enumerable.Empty<ReaderPost>. Это по-прежнему мало неудовлетворительно, потому что если возникает ошибка, свойство будет установлено. Вы можете создать полный пользовательский конвертер, чтобы сделать это как более полное решение.

Вот конвертер, который будет заботиться об этом:

public class PostsConverter : JsonConverter 
{ 
    public override object ReadJson(
     JsonReader reader, 
     Type objectType, 
     object existingValue, 
     JsonSerializer serializer) 
    { 
     JToken val = JValue.ReadFrom(reader); 
     object result = null; 

     if (val.Type == JTokenType.Array) 
     { 
      result = val.ToObject<IEnumerable<ReaderPost>>(); 
     } 
     else if (val.Type == JTokenType.Boolean) 
     { 

      result = Enumerable.Empty<ReaderPost>(); 
     } 

     return result; 
    } 

    public override void WriteJson(
     JsonWriter writer, 
     object value, 
     JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override bool CanConvert (Type type) 
    { 
     return typeof(IEnumerable<ReaderPost>).IsAssignableFrom(type); 
    } 

    public override bool CanRead 
    { 
     get { return true; } 
    } 
} 

Использование:

var settings = new JsonSerializerSettings(); 

settings.Converters = new [] { new PostsConverter() }; 

GetReaderResponse resp = 
    JsonConvert.DeserializeObject<GetReaderResponse>(json, settings); 

Пример:https://dotnetfiddle.net/i9CXwp

+0

Спасибо! это, кажется, хорошо работает – Shubhan

0

попробовать это:

public class GetReaderResponse 
{ 
    public bool posts { get; set; } 
    public ReaderPost[] post { get; set; } 
} 
+0

извините, но я исправил опечатку в формате JSON. Я получаю «сообщения» оба раза. Ваш ответ не помогает. – Shubhan

1

Используя JSON.NETs встроенные в LINQ к JSON, вы можете попробовать коснуться, как это:

JObject jObject = JObject.Parse(json); 
GetReaderResponse response = new GetReaderResponse(); 
if (jObject["posts"] is JArray) 
    response = jObject.ToObject<GetReaderResponse>(); 

// Do something with the response object. 

где json переменная является JSON строка, необходимо десериализовать.

0

После прочтения комментария Илии, я думаю, я мог бы найти ответ. Я не хочу не использовать строковые литералы, так я изменил мой класс GetReaderResponse выглядеть следующим образом:

public class GetReaderResponse 
{ 
    public dynamic posts {get; set;} 
    public IEnumerable<ReaderPost> Posts 
    { 
     get 
     { 
      if (posts is bool) 
       return new ReaderPost[0]; 

      return posts.ToObject<IEnumerable<ReaderPost>>();    
     } 
    } 
} 

ли этот звук штраф или это выглядит грязно?

Смежные вопросы