等标准
我有一个对象:
[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);
}
}
如果您正在寻找特定的输出,我认为您不会找到比现有更干净的解决方案。如果您的real目标是以紧凑的方式序列化JSON,请参阅BSON或ProtoBuf
这应该能胜任你的工作。我只是为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您希望使用自定义转换器。因此,无论您想在哪里使用它,都必须调用through属性。
我也在做类似的事情,我必须手动调用转换器。
/// <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; }