使用其他名称反序列化属性?

时间:2015-02-02 22:30:25

标签: c# json

我有一个接口,公开了一个名为Pages的属性:

public interface INameSet
{
    IQueryable<string> Names { get; }
}

我有这个实现接口的类,还必须从JSON对象中解析:

[DataContract(Name = "surveyPageSet")]
public class SurveyPage : INameSet
{
    [DataMember(Name = "names")]
    public List<string> SurveyNames { get; set; }

    public IQueryable<string> Names
    {
        get
        {
            //Returns SurveyNames after some filtration logic
        }
    }
}

我的问题是当我传入这个对象时:

{
    "names": ["testname"]
}

JSON解释器正在尝试反序列化它以匹配Names属性而不是SurveyNames属性。我知道这是因为在删除接口的实现并将SurveyNames更改为Names时,它会很好地填充属性。有没有办法让它序列化到正确的属性,还是我需要创建一个能够生成INameSet接口正确结果的转换器类?

编辑:这是内置的序列化程序。如果有一个使用Newtonsoft / JSON.NET的解决方案对我没问题。

1 个答案:

答案 0 :(得分:3)

JavaScriptSerializer不允许重新开始使用名称,因此请勿使用它。

相反,请使用Json.NETDataContractJsonSerializer。实际上,根据您应用的数据协定属性,两者都应该已经工作。

例如,使用Json.NET,如果我这样做:

        var page1 = JsonConvert.DeserializeObject<SurveyPage>(json);
        Debug.Assert(page1.SurveyNames != null && page1.SurveyNames.SequenceEqual(new string [] { "testname" }));

然后没有断言。同样,如果我这样做,则没有断言:

        var page2 = DataContractJsonSerializerHelper.GetObject<SurveyPage>(json);
        Debug.Assert(page2.SurveyNames != null && page2.SurveyNames.SequenceEqual(new string[] { "testname" }));

使用助手类:

public static class DataContractJsonSerializerHelper
{
    private static MemoryStream GenerateStreamFromString(string value)
    {
        return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
    }

    public static string GetJson<T>(T obj, DataContractJsonSerializer serializer)
    {
        using (var memory = new MemoryStream())
        {
            serializer.WriteObject(memory, obj);
            memory.Seek(0, SeekOrigin.Begin);
            using (var reader = new StreamReader(memory))
            {
                return reader.ReadToEnd();
            }
        }
    }

    public static string GetJson<T>(T obj) where T : class
    {
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
        return GetJson(obj, serializer);
    }

    public static T GetObject<T>(string json) where T : class
    {
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
        return GetObject<T>(json, serializer);
    }

    public static T GetObject<T>(string json, DataContractJsonSerializer serializer)
    {
        T obj = default(T);
        using (var stream = GenerateStreamFromString(json))
        {
            obj = (T)serializer.ReadObject(stream);
        }
        return obj;
    }
}

<强>更新

如果您真的想继续使用JavaScriptConverter,可以编写自己的JavaScriptConverter并手动反序列化每个字段。但这很麻烦,我不推荐它。