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

时间:2011-05-01 19:50:41

标签: c# json serialization

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

它将resultObject作为数组: resultObject:[{object1},{object2},...] 如果有多个对象 然后它回来了 resultObject:{object1 }如果只有一个对象。

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

2 个答案:

答案 0 :(得分:1)

我已经找到了大量难看的解决方案,但到目前为止:

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

我还尝试使用KnownTypes和DataContractJsonSerializer,但是数据提取序列化程序需要以特殊命名属性的形式提供“提示”以帮助它反序列化。 (Why am I using the KnownType attribute wrong?)。如果您对序列化没有任何控制权,那么这是一个绝望的策略,我猜你就是这种情况。

所以现在我们已经找到了一个难以理解的解决方案,其中试错法是我的首选: 使用ScriptSerializer时,如果出现任何错误,转换将失败并显示InvalidOperationException。然后我创建了两个数据类型,一个是data-as-arrays,另一个是data是单个实例(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并手动将数据对象添加到数据列表:

    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);
    }

我不是说这是一个漂亮的解决方案(事实并非如此),但它应该能够胜任。

您还可以查看json.net,它似乎是.NET中首选的json序列化程序:How to install JSON.NET using NuGet?

答案 1 :(得分:0)

好吧,我的服务提供商最后说这真的是一个bug。

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

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