c# - 使用不同的名称反序列化属性?

标签 c# json

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

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

我有一个实现接口(interface)的类,并且还必须从 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 属性。我知道会发生这种情况,因为当删除接口(interface)的实现并将 SurveyNames 更改为 Names 时,它会很好地填充属性。有没有办法让它序列化到正确的属性,或者我是否需要创建一个翻译器类来生成 INameSet 接口(interface)的正确具体?

编辑:这是使用内置序列化器的。如果 Newtonsoft/JSON.NET 有一个解决方案,那对我来说就很好。

最佳答案

JavaScriptSerializer 不允许重新映射开箱即用的名称,因此请勿使用它。

相反,请使用 Json.NET或 DataContractJsonSerializer。事实上,考虑到您应用的数据协定属性,两者都应该已经工作。

例如,使用 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并手动反序列化每个字段。但这很麻烦,我不推荐它。

关于c# - 使用不同的名称反序列化属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28288034/

相关文章:

php - 如何在 PHP 中将数组插入数组中的数组

c# - JQuery勾选项CheckBoxList

c# - Process.StandardOutput.ReadToEnd() 中的死锁问题;

c# - 为什么 ToString() 并不总是适用于 DateTime 对象?

javascript - 从源 'http://github/..file.json' 访问位于 'null' 的 XMLHttpRequest 已被 CORS 策略 : 阻止

c# - 解码包含 JSON 字符串的 JSON 字符串

javascript - Google 可视化 API 示例中的 "Invalid JSON string"

android - 在 Android 中处理 JSON 数据的最佳策略是什么?

c# - FileHelpers在调用engine.ReadNext()方法和readign engine.LineNumber属性之间的线程锁定问题

c# - 等待多个任务会比第一个异常观察到更多吗?