【问题标题】:Rename Property from Deserialized Javascript从反序列化的 Javascript 重命名属性
【发布时间】:2013-03-29 18:23:29
【问题描述】:

如何反序列化 JavaScript 并更改正在处理的属性的名称?

例如:

class MyClass
{
public string CreateDate {get;set;}
}

public class DeserializeMyClass
{
//How do I take "create_date" and convert it to CreateDate? Is there an attribute I
//can use?
var json = @"{""create_date"":""04/12/2013""}";
var ds = new JavaScriptSerializer();

ds.Deserialize<MyClass>(json);

}

提前致谢!

【问题讨论】:

  • 除此之外 - 你可能不想像这样传递日期。您将遇到各种日期格式的本地化问题。使用固定格式,例如 ISO8601 DateTime.ToString("o") 并在 javascript 中与 Moment.js 配对。
  • 当然,我只是想举个简单的例子。

标签: c# javascript .net deserialization custom-attributes


【解决方案1】:

对于 JavaScriptSerializer,您似乎无法轻松做到这一点,但您可以在 Json.Net 或使用 DataContractSerializer(.Net 框架的一部分)中做到这一点。

对于 Json.Net,您可以放置​​指定名称的 JsonProperty 属性。

class MyClass
{
  [JsonProperty(Name="create_date")]
  public string CreateDate {get;set;}
}

对于 DataContractSerializer 使用 DataMember 属性

【讨论】:

  • 这是在 Microsoft 程序集中找到的吗?
【解决方案2】:

JavaScriptSerializer 中没有对属性重命名的标准支持,但是您可以很容易地添加自己的:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;
using System.Reflection;

public class JsonConverter : JavaScriptConverter
{
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        List<MemberInfo> members = new List<MemberInfo>();
        members.AddRange(type.GetFields());
        members.AddRange(type.GetProperties().Where(p => p.CanRead && p.CanWrite && p.GetIndexParameters().Length == 0));

        object obj = Activator.CreateInstance(type);

        foreach (MemberInfo member in members)
        {
            JsonPropertyAttribute jsonProperty = (JsonPropertyAttribute)Attribute.GetCustomAttribute(member, typeof(JsonPropertyAttribute));

            if (jsonProperty != null && dictionary.ContainsKey(jsonProperty.Name))
            {
                SetMemberValue(serializer, member, obj, dictionary[jsonProperty.Name]);
            }
            else if (dictionary.ContainsKey(member.Name))
            {
                SetMemberValue(serializer, member, obj, dictionary[member.Name]);
            }
            else
            {
                KeyValuePair<string, object> kvp = dictionary.FirstOrDefault(x => string.Equals(x.Key, member.Name, StringComparison.InvariantCultureIgnoreCase));

                if (!kvp.Equals(default(KeyValuePair<string, object>)))
                {
                    SetMemberValue(serializer, member, obj, kvp.Value);
                }
            }
        }

        return obj;
    }


    private void SetMemberValue(JavaScriptSerializer serializer, MemberInfo member, object obj, object value)
    {
        if (member is PropertyInfo)
        {
            PropertyInfo property = (PropertyInfo)member;                
            property.SetValue(obj, serializer.ConvertToType(value, property.PropertyType), null);
        }
        else if (member is FieldInfo)
        {
            FieldInfo field = (FieldInfo)member;
            field.SetValue(obj, serializer.ConvertToType(value, field.FieldType));
        }
    }


    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        Type type = obj.GetType();
        List<MemberInfo> members = new List<MemberInfo>();
        members.AddRange(type.GetFields());
        members.AddRange(type.GetProperties().Where(p => p.CanRead && p.CanWrite && p.GetIndexParameters().Length == 0));

        Dictionary<string, object> values = new Dictionary<string, object>();

        foreach (MemberInfo member in members)
        {
            JsonPropertyAttribute jsonProperty = (JsonPropertyAttribute)Attribute.GetCustomAttribute(member, typeof(JsonPropertyAttribute));

            if (jsonProperty != null)
            {
                values[jsonProperty.Name] = GetMemberValue(member, obj);
            }
            else
            {
                values[member.Name] = GetMemberValue(member, obj);
            }
        }

        return values;
    }

    private object GetMemberValue(MemberInfo member, object obj)
    {
        if (member is PropertyInfo)
        {
            PropertyInfo property = (PropertyInfo)member;
            return property.GetValue(obj, null);
        }
        else if (member is FieldInfo)
        {
            FieldInfo field = (FieldInfo)member;
            return field.GetValue(obj);
        }

        return null;
    }


    public override IEnumerable<Type> SupportedTypes
    {
        get 
        {
            return new[] { typeof(MyClass) };
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class JsonPropertyAttribute : Attribute
{
    public JsonPropertyAttribute(string name)
    {
        Name = name;
    }

    public string Name
    {
        get;
        set;
    }
}

MyClass 类则变为:

class MyClass
{
     [JsonProperty("create_date")]
     public string CreateDate {get;set;}
}

我知道这可能有点晚了,但我认为其他想要使用 JavaScriptSerializer 而不是 Json.Net 或 'DataContractJsonSerializer` 的人可能会喜欢它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-09
    • 2016-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-01
    • 1970-01-01
    相关资源
    最近更新 更多