2014-09-19 78 views
1

的我有一个对象:序列化对象到阵列

[JsonConverter(typeof(MessageConverter))] 
public class Message 
{ 
    [JsonProperty(Order = 1)] 
    public long Id { get; set; } 
    [JsonProperty(Order = 2)] 
    public string Msg { get; set; } 
    [JsonProperty(Order = 3)] 
    public int Timestamp { get; set; } 
} 

哪我想连载到以下形式的在JSON数组:

[long, string, int] 

这个类将被嵌套在层次结构,所以自动转换将是首选。

我目前使用下面的代码,但这似乎包含大量的重复。

我想知道是否有一个属性/更紧凑的解决方案,可以让JSON.NET使用提供的属性提供相同的功能,而无需转换器。

public class MessageConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(Message); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var arr = serializer.Deserialize<JToken>(reader) as JArray; 

     if (arr == null || arr.Count != 3) 
      throw new JsonSerializationException("Expected array of length 3"); 

     return new Message 
     { 
      Id = (long)arr[0], 
      Msg = (string)arr[1], 
      Timestamp = (int)arr[2] 
     }; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var msg = value as Message; 
     var obj = new object[] { msg.Id, msg.Msg, msg.Timestamp }; 
     serializer.Serialize(writer, obj); 
    } 
} 

回答

1

如果你正在寻找一个特定的输出,我不认为你会发现比你有什么清晰的解决方案。如果您的real的目标是以紧凑的方式序列化JSON,请查看BSON或ProtoBuf等标准

+0

谢谢,我正在寻找代码的紧凑性而不是输出的紧凑性。看起来可能存在一个通用的解决方案,所以我最终可能会编码我自己的。我会等一会儿再接受你的回答。 – user1112560 2014-09-19 01:05:13

+0

是的,如果你不需要这个确切的输出,使用protobuf或bson库也会减少你的代码,因为一般的解决方案将在那个库中 – 2014-09-19 01:09:29

1

这应该是你的工作。我只写了WRITE即输出。

namespace Test 
{ 
    using Newtonsoft.Json; 
    using Newtonsoft.Json.Linq; 
    using System; 
    using System.Collections; 
    using System.Reflection; 

    /// <summary> 
    /// Defines the custom JSON Converter of collection type that serialize collection to an array of ID for Ember. 
    /// </summary> 
    public class CustomConverter : JsonConverter 
    { 
     /// <summary> 
     /// Define the property name that is define in the collection type. 
     /// </summary> 
     private readonly string IDKEY = "Id"; 

     private readonly string MSGKEY = "Msg"; 

     private readonly string TIMEKEY = "Timestamp"; 

     /// <summary> 
     /// It is write only convertor and it cannot be read back. 
     /// </summary> 
     public override bool CanRead 
     { 
      get { return false; } 
     } 

     /// <summary> 
     /// Validate that this conversion can be applied on IEnumerable type only. 
     /// </summary> 
     /// <param name="objectType">type of object</param> 
     /// <returns>Validated value in boolean</returns> 
     public override bool CanConvert(Type objectType) 
     { 
      return objectType == typeof(Message); 
     } 

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 
      JsonSerializer serializer) 
     { 
      throw new NotImplementedException(); 
     } 

     /// <summary> 
     /// Write JSON data from IEnumerable to Array. 
     /// </summary> 
     /// <param name="writer">JSON Writer</param> 
     /// <param name="value">Value of an object</param> 
     /// <param name="serializer">JSON Serializer object</param> 
     public override void WriteJson(JsonWriter writer, object item, JsonSerializer serializer) 
     { 
      JArray array = new JArray(); 
      PropertyInfo prop = item.GetType().GetProperty(IDKEY); 
      if (prop != null && prop.CanRead) 
      { 
       array.Add(JToken.FromObject(prop.GetValue(item, null))); 
      } 

      prop = item.GetType().GetProperty(MSGKEY); 
      if (prop != null && prop.CanRead) 
      { 
       array.Add(JToken.FromObject(prop.GetValue(item, null))); 
      } 

      prop = item.GetType().GetProperty(TIMEKEY); 
      if (prop != null && prop.CanRead) 
      { 
       array.Add(JToken.FromObject(prop.GetValue(item, null))); 
      } 


      array.WriteTo(writer); 
     } 
    } 
} 

您正在告诉JSON.NET您要使用自定义转换器。所以如果你想使用它,你将不得不通过属性来调用。

我也在做类似的事情,我必须手动调用转换器。

/// <summary> 
     /// Gets or sets collection of documents. 
     /// </summary> 
     [JsonConverter(typeof(IDWriteListConverter))] 
     public ICollection<Document> Documents { get; set; } 

     /// <summary> 
     /// Gets or sets collection of comments. 
     /// </summary> 
     [JsonConverter(typeof(IDWriteListConverter))] 
     public ICollection<Comment> Comments { get; set; } 

     /// <summary> 
     /// Gets or sets the collection of transactions. 
     /// </summary> 
     [JsonConverter(typeof(IDWriteListConverter))] 
     public virtual ICollection<Transaction> Transactions { get; set; } 
+0

这完全没有回答我的问题。 OP中已经提供了一个工作转换器,它可以用更少的代码提供更多的功能。 – user1112560 2014-09-19 00:54:47

+0

没有内置功能。 – codebased 2014-09-19 01:00:13