JsonConvert属性似乎被跳过了。为什么?

时间:2013-11-04 14:44:30

标签: c# json serialization enums

我有很多属性,我正在尝试使用Json.NET进行序列化。复杂对象工作正常,因为我必须将它们放在它们之上是[JsonProperty(“name”)]属性。

不幸的是,我一直在努力让这个与任何枚举一起使用。理想情况下,我希望能够通过以下方式来定义属性:

MyValue = ThisEnum.First;

并让我的类中的属性自动将枚举序列化为相应的更改值名称(因为这个问题问:Control enum value format during (de)serialization via attributes。不幸的是,我写了一些自定义转换器并试图应用建议我之前的一个问题(Can't get enum to convert to json properly using Json.NET)中的人,尽管该线程中的受访者给出的答案看起来像他们的工作,但在我的解决方案中,他们没有任何效果。

例如,给定这类属性:

public class Animal
{
    [JsonProperty("id")]
    public string Id {get;set;}

    [JsonProperty("types")]
    [JsonConverter(typeof(StringEnumConverter))]
    public AnimalType Types {get;set;}

    [JsonProperty("created")]
    [JsonConverter(typeof(MyDateTimeToSecondsSinceEpochConverter))]
    public DateTime Created {get;set;}
}

在AnimalType枚举中:

public enum AnimalType
{
    [EnumMember(Value="black_rhino")]
    BlackRhino,
    [EnumMember(Value="wild_pig")]
    WildPig,
    [EnumMember(Value="chicken")]
    Chicken
}

在MyDateTimeToSecondsSinceEpochConverter类中:

public class MyDateTimeToSecondsSinceEpochConverter : DateTimeConverterBase
{
    public override WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteRawValue(@"""\/Date(" + ConvertDateTimeToEpoch((DateTime)value).ToString() + @")\/""");
    }

    public override ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.Value == null) return null;
        if (reader.TokenType == JsonToken.Integer)
            return ConvertEpochToDateTime((long)reader.Value);
        return DateTime.Parse(reader.Value.ToString());
    }

    public DateTime ConvertEpochToDateTime(long seconds)
    {
        return new DateTime(1970, 1, 1).AddSeconds(seconds);
    }

    public long ConvertDateTimeToEpoch(DateTime dateTime)
    {
        var epochStart = new DateTime(1970,1,1);
        if (dateTime < epochStart) return 0;
        return Convert.ToInt64(dateTime.Subtract(epochStart).TotalSeconds);
    }
}

在我的通话方法中,我可以有类似的东西:

var data  = new Animal {
    Id = "123abc",
    Types = AnimalType.BlackRhino,
    Created = new DateTime(2014,3,15)
}

我使用一种方法来逐步浏览对象的每个属性,只需要列出每个属性以及值的HTML编码输出并将它们全部放在一个字符串中(我稍后会附加)到URL):

public static string GetString(Animal animal)
{
    var result = "";
    foreach( var property in animal.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
    {
        foreach(var attribute in property.GetCustomAttributes(false))
        {
            var name = (JsonPropertyAttribute)attribute;
            var value = property.GetValue(animal, null);
            if (value != null)
            {
                if (!string.Empty(result))
                    result += "&";
                result += string.Format("{0}={1}", name.PropertyName, HttpUtility.UrlEncode(value.ToString()));
            }
        }
    }
    return result;
}

不幸的是,当我运行时,我看到了:

'id=abc123&type=BlackRhino&created=3%2f15%2f2014+12%3a00%3a00+AM'

有没有人对如何让两个JsonConverters实际进行转换有任何想法? JsonProperty名称显然在变化,但是'BlackRhino'没有变为'black_rhino',也没有将DateTime转换为long。

我理想地在属性中寻找某些东西或使用这些转换器,这样我就不必为我在项目中使用的每个枚举编写一个get / set,而只需应用属性并完成它。

谢谢!

1 个答案:

答案 0 :(得分:1)

您可以让Json.NET将您的对象转换为字符串,然后转换为字典,这是一个名称/值对的集合,如查询字符串。

public static string GetString(Animal animal)
{
    var result = "";
    var serialized = JsonConvert.SerializeObject(animal);
    var dict = JsonConvert.DeserializeObject<IDictionary<string, string>>(serialized);
    foreach (var pair in dict)
    {
        if (!string.IsNullOrEmpty(result))
            result += "&";
        result += string.Format("{0}={1}", pair.Key, HttpUtility.UrlEncode(pair.Value.ToString()));
    }
    return result;
}

以您的示例为例:

id=123abc&types=black_rhino&created=%2fDate(1394841600)%2f