2015-12-07 3 views
1

Я звоню в службу отдыха, и служба возвращает содержимое JSON. Большая часть контента имеет предопределенную структуру, но часть контента динамически основана на параметрах, которые были переданы в службу отдыха. Как только я получаю ответ от службы остального, я хочу десериализовать объект, чтобы я мог легко использовать данные. В настоящее время я использую DataContractJsonSerializer для этого.JSON десериализация для объекта с частичными динамическими свойствами

/// <summary> 
/// Deserialize JSON formatted string to an object of a specified type 
/// </summary> 
/// <typeparam name="T">Object type to deserialize</typeparam> 
/// <param name="sJSON">JSON formatted string to deserialize</param> 
/// <returns>Returns an instance of an object</returns> 
public static T FromJSON<T>(this string sJSON) where T : new() 
{ 
    T oValue; 

    using (System.IO.MemoryStream strJSON = new System.IO.MemoryStream()) 
    { 
     using (System.IO.StreamWriter swJSON = new System.IO.StreamWriter(strJSON)) 
     { 
      swJSON.Write(sJSON); 
      swJSON.Flush(); 

      strJSON.Seek(0, System.IO.SeekOrigin.Begin); 

      System.Runtime.Serialization.Json.DataContractJsonSerializer ser = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(T)); 
      oValue = (T)ser.ReadObject(strJSON); 

      return oValue; 
     } 
    } 
} 

Вот пример ответа остальные службы:

{ 
    "entities" : [{ 
      "type" : "mytest", 
      "properties" : { 
       "Active" : true, 
       "Category" : "10732", 
       "Description" : "test test test", 
       "LastUpdateTime" : 1446676525195, 
       "Id" : "12655" 
      } 
     } 
    ], 
    "metadata" : { 
     "status" : "OK", 
     "count" : 0 
    } 
} 

объект всегда будет иметь «сущностей» и свойство «метаданных», метаданные будут всегда иметь «статус» и " count ", и сущности всегда будут массивом, и каждый элемент в массиве будет иметь свойство типа и свойства. Динамический характер вступает в игру для объекта properties, который будет содержать свойства, полностью основанные на том, что было передано в службу отдыха.

Это определение класса, которое я использовал для десериализации строки json в объекты. Но я не уверен, как сделать динамическую часть свойств. Даже если бы я мог закончить словарь значений имен, которые были бы работоспособными. Возможно ли это, в идеале, без требований сторонних json-библиотек?

[DataContract] 
public class Response 
{ 
    [DataMember(
    public Entity[] entities { get; set; } 

    [DataMember(
    public MetaData metadata { get; set; } 
} 

[DataContract] 
public class Entity 
{ 
    [DataMember(
    public string type { get; set; } 

    [DataMember()] 
    public Properties properties { get; set; } 
} 


[DataContract] 
public class Properties 
{ 
    //How do I make this part dynamic? 
} 

[DataContract] 
public class MetaData 
{ 
    [DataContract] 
    public enum Status 
    { 
     [EnumMember] 
     OK, 

     [EnumMember] 
     FAILED 
    } 

    public Status CompletionStatus { get; set; } 

    [DataMember()] 
    public string status 
    { 
     get 
     { 
      return this.CompletionStatus.ToString(); 
     } 
     set 
     { 
      this.CompletionStatus = (Status)Enum.Parse(typeof(Status), value); 
     } 
    } 

    [DataMember()] 
    public int count{ get; set; } 
} 
+2

Сделать свойствами а 'Dictionary ' – Rob

+0

@Rob - это не похоже на работу. Свойство «Свойства» всегда имеет счет 0. – Jeremy

+0

более пристально посмотрел на него - вам также нужно настроить сериализатор для правильной сериализации объектов/словарей JSON - см. Ответ отправленный – Rob

ответ

1

Изменить вашу собственность это:

[DataMember] 
public Dictionary<string, object> properties { get; set; } 

И тогда вам нужно настроить сериалайзер:

var ser = new DataContractJsonSerializer(typeof(T), new DataContractJsonSerializerSettings { 
    UseSimpleDictionaryFormat = true 
}); 
+0

Альтернативно, если вы используете JSON.net для сериализации, ll обрабатывать его автоматически –

+1

Ой, это здорово! Лучше, чем подход, который я предпринял, чтобы создать класс, реализующий ISerializable, затем используйте конструктор (информация SerializationInfo, StreamingContext); – Jeremy

1

Так я помещен часть вашего кода в приложение консоли и играл с ним немного, и то, что вы хотите использовать, называется динамическим типом.

Вот мой код:

static void Main(string[] args) 
{ 
     string test = @" [{ 
     ""type"" : ""mytest"", 
     ""properties"" : { 
      ""Active"" : true, 
      ""Category"" : ""10732"", 
      ""Description"" : ""test test test"", 
      ""LastUpdateTime"" : 1446676525195, 
      ""Id"" : ""12655"" 
     } 
    }, 
{ 
     ""type"" : ""mytest1"", 
     ""properties"" : { 
      ""Active"" : true, 
      ""Category"" : ""10731232"", 
      ""Description"" : ""test test1 test"", 
      ""LastUpdateTime"" : 144195, 
      ""Id"" : ""126155"" 
     } 
    } 
]"; 
     List<Entity> entities = JsonConvert.DeserializeObject<List<Entity>>(test); 
     foreach (Entity e in entities) 
     { 
      Console.WriteLine(e.properties.Active); 
     } 
     Console.ReadKey(); 
} 

Вот мой класс:

public class Entity 
    { 
     public string type { get; set; } 
     public dynamic properties { get; set; } 
    } 

Так, так как свойства динамичны он получает данные из JSon и решает, что его структура должна выглядит. Я использовал Newtsoft для десериализации, но концепция должна оставаться неизменной. быть также осторожным, так как она динамична некоторые типы как логическое значение не может передавать более правильно, поэтому убедитесь, что, когда вы получите его в C#, чтобы получить их правильные типы соответствуют

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