繁体   English   中英

.NET 序列化 JSON 数据的动态结构(模式)

[英].NET serialization of JSON data with dynamic structure (schema)

web 服务我使用 json 数据进行响应。

如果有多个 object,它将 resultObject 作为数组提供: resultObject:[{object1}, {object2},...]如果只有一个 object,则返回resultObject:{object1 }。

为了在 .NET 中序列化,我为 map json 模式创建了一个“静态”类结构。 但是,如果在一种情况下我有一个对象数组(列表),而在另一种情况下只有一个 object,如何处理这种情况?

我已经找到了很多丑陋的解决方案,但到目前为止:

如果您使用System.Web.Script.Serialization.JavaScriptSerializer您的控制非常有限。 如果结果数据类型很简单,你可以简单地使用DeserializeObject方法; 它将所有内容翻译成字典,并且“resultObject”属性在第一种情况下将是字典,而后一种情况会将其转换为此类字典的数组。 它不会为您省去最终翻译的麻烦,但您会将数据放入字典中,这可以被认为是第一步。

我还尝试使用 KnownTypes 和 DataContractJsonSerializer,但可惜 datacontract 序列化程序需要特殊命名属性形式的“提示”来帮助它反序列化。 为什么我错误地使用了 KnownType 属性? )。 如果您对序列化没有任何控制权,这是一个无望的策略,我猜您就是这种情况。

因此,现在我们要考虑最丑陋的解决方案,其中试错是我的首选:使用 ScriptSerializer 时,如果出现任何错误,转换将失败并返回 InvalidOperationException。 然后,我创建了两种数据类型,一种是数据作为数组,另一种是数据是单个实例(DataClass 是我的发明,因为您没有指定数据类型):

    [DataContract]
    public class DataClass
    {
        [DataMember]
        public string FirstName { get; set; }
        [DataMember]
        public int BirthYear { get; set; }

        public override string ToString()
        {
            return "FirstName : '" + FirstName + "', BirthYear: " + BirthYear;
        }
    }

    [DataContract]
    public class ResultSingle 
    {
        [DataMember]
        public DataClass Data { get; set; }
    }

    [DataContract]
    public class ResultArray 
    {
        [DataMember]
        public List<DataClass> Data { get; set; }
    }

使用这些数据类型,可以使用

        JavaScriptSerializer jSer = new JavaScriptSerializer();
        var one = jSer.Deserialize<ResultSingle>(jsonWithSingleInstance);
        var many = jSer.Deserialize<ResultArray>(jsonWithArray);

但这当然需要您提前知道数据类型,并且您会得到两种不同的结果类型。 相反,您可以选择始终转换为 ResultArray。 如果遇到异常,应转换为 ResultSingle,然后实例化 ResultArray 并手动将数据 object 添加到数据列表中:

    static ResultArray ConvertJson(string json)
    {
        ResultArray fromJson;
        JavaScriptSerializer jSer = new JavaScriptSerializer();
        try
        {
            fromJson = jSer.Deserialize<ResultArray>(json);
            return fromJson;
        }
        catch (InvalidOperationException)
        {
            var single = jSer.Deserialize<ResultSingle> (json);
            fromJson = new ResultArray();
            fromJson.Data = new List<DataClass>();
            fromJson.Data.Add(single.Data);
            return fromJson;
        }
    }

    static void Main(string[] args)
    {
        var jsonWithSingleInstance = "{\"Data\":{\"FirstName\":\"Knud\",\"BirthYear\":1928}}";
        var jsonWithArray = "{\"Data\":[{\"FirstName\":\"Knud\",\"BirthYear\":1928},{\"FirstName\":\"Svend\",\"BirthYear\":1930}]}";

        var single = ConvertJson(jsonWithSingleInstance);
        var array = ConvertJson(jsonWithArray);
    }

我并不是说这是一个漂亮的解决方案(它不是),但它应该可以完成这项工作。

You could also look at json.net which seem to be the json serializer of choice in .NET: How to install JSON.NET using NuGet?

嗯,我的服务商最后说真的是bug。

http://jira.codehaus.org/browse/JETTISON-102

说那是因为他们使用的 java 版本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM