对象到数组的序列化

时间:2014-09-19 00:40:07

标签: c# json.net

我有一个对象:

[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);
    }
}

2 个答案:

答案 0 :(得分: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; }

答案 1 :(得分:1)

如果您正在寻找特定的输出,我认为您不会找到比您拥有的更清洁的解决方案。如果真正的目标是以紧凑的方式序列化JSON,请查看BSON或ProtoBuf等标准