2016-05-30 4 views
0

Я пытаюсь сериализовать класс в строку JSON. Во-первых, мой фактический код:Newtonsoft JSON сериализует шаблон

// Note that this class is inside a PCL 
public class CommunicationMessage { 

    public String Key { get; set; } 

    public String Value { get; set; } 

    public List<CommunicationMessage> Childs { get; set; } 
} 

Это шаблон, который может быть преобразован в XML, которые могли бы выглядеть следующим образом:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<myproject> 
    <communicationmessage> 
     <header> 
      <participantid>1</participantid> 
      <deviceid>54325</deviceid> 
      <devicetype>Smartphone Samsung 4500</devicetype> 
      <timestamp>3456453445</timestamp> 
      <location>343-5343-64353</location> 
      <networkid>32</networkid> 
      <messageid>4003</messageid> 
     </header> 
     <data> 
     </data> 
    </communicationmessage> 
</myproject> 

Как вы можете видеть, переменная Key является XML- Элемент, который называется, например, communicationmessage.

Теперь U хочет шаблон неоспоримым преобразуется в строку JSON, но уверен, что я получаю вместо элемента communicationmessage элемент «Key»: «communicationmessage». Есть ли способ получить что-то для элемента вроде «mymessage»: «Это тест» где «mymessage» - это ключ и «Это тест» значение?

Спасибо за любую помощь

Solution

я решил его с этим кодом

public class CommunicationMessageJSONSerializer : JsonConverter { 

    /// <summary> 
    /// Used to 
    /// </summary> 
    /// <param name="objectType"></param> 
    /// <returns></returns> 
    public override bool CanConvert(Type objectType) { 
     return typeof(CommunicationMessage).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo()); 
    } 

    /// <summary> 
    /// Deserializes the JSON string 
    /// </summary> 
    /// <param name="reader"></param> 
    /// <param name="objectType"></param> 
    /// <param name="existingValue"></param> 
    /// <param name="serializer"></param> 
    /// <returns></returns> 
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { 

     // Load the JSON object from the reader 
     JObject jsonObject = JObject.Load(reader); 

     // Get the First Token 
     JToken token = jsonObject.Children().First(); 

     // The deserialized message 
     CommunicationMessage msg = ReadJSON(token); 
     return msg; 
    } 

    /// <summary> 
    /// This is the base method when deserializing a JSON string 
    /// </summary> 
    /// <param name="token"></param> 
    /// <returns>The root CommunicationMessage</returns> 
    private CommunicationMessage ReadJSON(JToken token) { 

     CommunicationMessage root = new CommunicationMessage(); 

     if (token is JProperty) { 
      if (token.First is JValue) { 
       root.Key = ((JProperty)token).Name; 
       root.Value = (string)((JProperty)token).Value; 
      } else { 
       root.Key = ((JProperty)token).Name; 

       foreach (JToken child in token.Children()) { 
        ReadRecursive(child, ref root); 
       } 
      } 
     } else { 
      foreach (JToken child in token.Children()) { 
       ReadRecursive(child, ref root); 
      } 
     } 
     return root; 
    } 

    /// <summary> 
    /// This is the recursive method when deserializing a JSON string 
    /// </summary> 
    /// <param name="token"></param> 
    /// <param name="root">The root of the coming messages</param> 
    private void ReadRecursive(JToken token, ref CommunicationMessage root) { 

     if (token is JProperty) { 

      CommunicationMessage msg = new CommunicationMessage(); 

      if (token.First is JValue) { 
       msg.Key = ((JProperty)token).Name; 
       msg.Value = (string)((JProperty)token).Value; 
      } else { 
       msg.Key = ((JProperty)token).Name; 

       foreach (JToken child in token.Children()) { 
        ReadRecursive(child, ref msg); 
       } 
      } 
      root.Childs.Add(msg); 
     } else { 
      foreach (JToken child in token.Children()) { 
       ReadRecursive(child, ref root); 
      } 
     } 
    } 

    /// <summary> 
    /// Serializes a CommuicationMessage to a JSON string 
    /// </summary> 
    /// <param name="writer"></param> 
    /// <param name="value"></param> 
    /// <param name="serializer"></param> 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { 
     var msg = value as CommunicationMessage; 
     WriteRecoursive(writer, msg, serializer); 
    } 

    /// <summary> 
    /// This is the recursive method for serializing 
    /// </summary> 
    /// <param name="writer"></param> 
    /// <param name="msg"></param> 
    /// <param name="serializer"></param> 
    private void WriteRecoursive(JsonWriter writer, CommunicationMessage msg, JsonSerializer serializer) { 

     writer.WriteStartObject(); 
     writer.Formatting = Formatting.Indented; 

     writer.WritePropertyName(msg.Key); 

     if (msg.Childs.Count > 0) { 
      writer.WriteStartArray(); 

      foreach (CommunicationMessage child in msg.Childs) { 
       WriteRecoursive(writer, child, serializer); 
      } 

      writer.WriteEndArray(); 

     } else { 
      writer.WriteValue(msg.Value); 
     } 

     writer.WriteEndObject(); 
    } 
} 

Если у вас есть какие-либо идеи, чтобы улучшить код, дайте мне знать это. Я буду держать решение обновленным.

Спасибо всем за вашу помощь

+1

Один из способов - написать собственный сериализатор JSON (de). Поскольку большинство из них будут использовать имя свойства в качестве ключа и их значения как значения. Здесь должен быть пример того, как это сделать: http://blog.maskalik.com/asp-net/json-net-implement-custom-serialization/ – Sidewinder94

+0

Я помню это, но мне очень нравится писать собственный парсер , Может быть, есть еще один способ сделать это? –

+0

Это не пользовательский парсер. Вы будете использовать специальный метод, чтобы проинструктировать библиотеку, как вы хотите, чтобы объект был сериализован. Вы говорите сериализатору: 1. Я начинаю новый объект. 2. Я начинаю новое свойство. 3. его имя можно найти , его значение . 4. Это имущество закончилось. 5. Я закончил свой объект. – Sidewinder94

ответ

2

Помимо использования custom serialisation или реализации ISerializable, вы можете сделать следующее. Но учтите, что существует недостаток этого метода, при котором все свойства должны быть обернуты так, иначе свойства не будут сериализованы. Это быстрый и грязный метод хорош для небольших классов, но если вы создаете более сложные классы, это будет лучше реализовать ISerializable

public class CommunicationMessage : Dictionary<string, object>  
{ 
    //this "hack" exposes the "Child" as a List 
    public List<CommunicationMessage> Childs 
    { 
     get { 
      return (List<CommunicationMessage>)this["Childs"]; 
     } 
     set 
     { 
      this["Childs"] = value; 
     } 
    } 

    public CommunicationMessage() 
    { 
     this["Childs"] = new List<CommunicationMessage>(); 
    } 
} 

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

var m = new CommunicationMessage(); 
m["mymessage"] = "This is a test"; 

И выход должен выглядеть

{ 
    "Childs": [], 
    "mymessage": "This is a test" 
} 

альтернативой ISerializable реализация:

public class CommunicationMessage:ISerializable 
{ 
    public String Key { get; set; } 

    public String Value { get; set; } 

    public List<CommunicationMessage> Childs { get; set; } 

    public void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     info.AddValue(Key, Value); 

     PropertyInfo[] pi=this.GetType().GetProperties(); 
     foreach(var p in pi) 
     { 
      if (p.Name == "Key" || p.Name == "Value") 
       continue; 
      info.AddValue(p.Name, p.GetValue(this)); 
     } 
    } 
} 
+0

Ничего не думал о том, что использовать словарь – Sidewinder94

+0

с использованием интерфейса ** ISerializable ** кажется хорошим, но проблема в том, что класс ** CommunicationMessage ** находится внутри PCL, и нет возможности извлечь это в обычную библиотеку классов. –

+0

Где вы делаете фактическую сериализацию/десериализацию (например, фактическое вызов JsonConvert.Serialise)? Если вы делаете это за пределами PCL и можете обернуть/наследовать CommunicationMessage, я могу опубликовать другую альтернативную реализацию. –

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