2015-01-23 3 views
0

Использование C# и, в частности, JSON.net, как я могу работать с объектом JSON, который может иметь динамическое значение. Например:Deserialize JSON с неизвестным значением типа

{ "message_id": "123-456", "данные": [ "данные", "список"], "типа": "MSG_TYPE1" }

{ "message_id": "123-457", "данные": "мои строки данных", "типа": "MSG_TYPE2" }

{ "mESSAGE_ID": "123-458", «данные ": {" key1 ":" value1 "," key2 ":" value2 "}, " type ":" MSG_TYPE3 " }

Значение «данные» может быть любого типа. В C# я определил класс ServiceMessage, который содержит эти свойства, но каким типом свойства должны быть «данные». Я смотрел на JToken или JContainer, но я не уверен, что лучший способ реализовать.

public class ServiceMessage 
{ 
    public string message_id { get; set; } 
    public JContainer data { get; set; } 
    public string type { get; set; } 

    public string getJSON() 
    { 
     string json = JsonConvert.SerializeObject(this); 
     return json; 
    } 

    public void setJSON(string json) 
    { 
      dynamic jsonObj = JsonConvert.DeserializeObject(json); 

      this.message_id = jsonObj.message_id; 
      this.type = jsonObj.type; 
      this.data = // what goes here. 
    } 
} 
+0

вы знаете, что они реальную структуру объекта данных во время компиляции или будет содержать каждое сообщение разные значения? как вы ожидаете поискать значение данных? – dbarnes

+0

Я буду знать фактическую структуру объекта данных на основе типа сообщения. Если я знаю, что сообщение принадлежит MSG_TYPE1, тогда я узнаю структуру объекта. – Hugh

+0

@ Огромный, трудно иметь строго типизированный объект, не зная точно, как вы планируете получить доступ к объекту, который вы можете сделать с помощью генериков, но я уверен, что это вызовет больше проблем, чем это стоит. Как вы ожидаете получить доступ к данным, когда они попадут на провод? – dbarnes

ответ

0

Ну, я не уверен, что это правильно или нет, но это то, что я придумал. я почерпнул из here

class ServiceMessageConverter : CustomCreationConverter<ServiceMessage> 
{ 

    public override ServiceMessage Create(Type objectType) 
    { 
     return new ServiceMessage(); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var msg = new ServiceMessage(); 
     string data_string = ""; 

     //get an array of the object's props so I can check if the JSON prop s/b mapped to it 
     var objProps = objectType.GetProperties().Select(p => p.Name.ToLower()).ToArray(); 

     while (reader.Read()) 
     { 
      if (reader.Value == null) 
      { 
       continue; 
      } 
      // read the property name 
      string readerValue = reader.Value.ToString().ToLower(); 

      // read the property value 
      if (reader.Read()) 
      { 
       // make sure the complex types are saved as strings 
       if (readerValue.ToLower() == "data") 
       { 
        if (reader.TokenType == JsonToken.StartObject) 
        { 
         dynamic data_obj = serializer.Deserialize(reader); 
         data_string = data_obj.ToString(); 
        } 
        else if (reader.TokenType == JsonToken.StartArray) 
        { 
         dynamic data_obj = serializer.Deserialize(reader); 
         data_string = data_obj.ToString(); 
        } 
        else 
        { 
         data_string = reader.Value.ToString(); 
        } 
        // stuff the data element value into the ServiceMessage 
        PropertyInfo pi = msg.GetType(). 
         GetProperty("data", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); 
        pi.SetValue(msg, data_string); 
       } 
       else 
       { 
        // stuff the value into the ServiceMessage 
        PropertyInfo pi = msg.GetType(). 
         GetProperty(readerValue, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); 
        var convertedValue = Convert.ChangeType(reader.Value, pi.PropertyType); 
        pi.SetValue(msg, convertedValue, null); 
       } 

      } 
     } 
     return msg; 

    } 
} 
0

Что вы делаете с данными? Было бы разумно оставить его как строку json и обрабатывать его, когда данные необходимы.

+0

Когда известны идентификатор сообщения и тип сообщения, извлекается элемент данных. JSON исходит от производителя питона (но это может быть что угодно). Я думал хранить данные как строку JSON, а затем обрабатывать, когда это необходимо, но я не был уверен, есть ли лучший способ? – Hugh

+0

http://stackoverflow.com/questions/13652983/dynamic-jcontainer-json-net-iterate-over-properties-at-runtime имеет некоторую информацию, но на основе того, как выглядят ваши объекты. Я оставил бы его как строку из-за того, что вам все равно придется десериализовать. По крайней мере, когда вы вытаскиваете его по типу сообщения, я предполагаю, что, по крайней мере, структура будет следовать заданному шаблону и позволит вам продолжать, как и раньше. – aminner

+0

Спасибо. Таким образом, будучи новичком в этом, я дезертировал «данные», и похоже, что JSON.Net обнаруживает массив JSON, объект и т. Д. Итак, как я могу убедиться, что конкретное поле остается в виде строки? – Hugh

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