我正在寻找一种方法从Json进行反序列化,使用Json本身的数据依赖于版本。
我的目标是使用ServiceStack.Text.JsonDeserializer
,但可以切换到另一个库。
例如,我想在JSON中为v1.0定义数据:
{
version: "1.0"
condition: "A < B"
}
然后,数据的下一个版本(比如说2.0)将是:
{
version: "2.0"
condition: ["A < B", "B = C", "B < 1"]
}
最后,我希望能够验证数据的版本,以了解如何正确反序列化JSON。
更新
看起来在已知产品中对版本相关的JSON(反)序列化没有任何隐式支持。
正确的解决方案似乎是通过(de)仅序列化版本部分来分割任务,然后使用隐式(de)序列化来获得正确的类型。
感谢所有分享有关问题的知识和想法的人。
答案 0 :(得分:4)
您可以做的是以下内容:
version
字段的基类,而不是其他任何内容。一个例子(使用System.Web.Script.Serialization.JavaScriptSerializer
):
class BaseClass
{
public int version { get; set; }
}
class FirstVersion: BaseClass
{
public string condition { get; set; }
}
class SecondVersion: BaseClass
{
public IEnumerable<string> condition { get; set; }
}
public void Deserialize (string jsonString)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
BaseClass myData = serializer.Deserialize<BaseClass>(jsonString);
switch (myData.version)
{
case 1:
FirstVersion firstVersion = serializer.Deserialize<FirstVersion>(jsonString);
// ...
break;
case 2:
SecondVersion secondVersion = serializer.Deserialize<SecondVersion>(jsonString);
// ...
break;
}
}
如您所见,此代码将数据反序列化两次 - 如果您正在处理大型数据结构,则可能会出现问题。如果您想不惜一切代价避免这种情况,您必须放弃静态类型或修改应用程序的数据模型。
以下是dynamic
的样子:
public void Deserialize (string jsonString)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic myData = serializer.Deserialize<object>(jsonString);
if (myData ["version"] == 1) {
...
}
}
还可以选择编写自己的自定义JavaScriptConverter。这是更多的工作,但我很确定你可以实现你想要的东西,它看起来会更好。
要考虑的另一个建议是永远不要从JSON结构中删除属性。如果您需要修改属性,请保留旧属性并添加新属性 - 这样,旧代码始终可以从较新的代码中读取数据。当然,如果您经常修改数据结构,这可能会很快失控......
在Java中,您可以使用Google的GSON库,因为它有built-in support for versioning。我没有调查它,但它是open source,如果它对你真的很重要,我猜你可以将实现移植到另一种语言。
答案 1 :(得分:1)
我建议您使用json.net,它允许您添加可用于版本控制的自定义类型转换。
问题不是序列化,因为它总是使用当前架构。问题是当客户端使用与接收对象的服务器不同的类型版本时。
您需要做的是在类型转换器中以编程方式检查版本并自行转换值(在这种情况下将字符串转换为数组)。
文档:http://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm
答案 2 :(得分:0)
您可能想要使用NewtonSoft.Json NuGET package。
这是.NET社区中的一种标准。它通常也被称为Json.NET
您可以像这样使用它(官方网站example):
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string output = JsonConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "ExpiryDate": "2008-12-28T00:00:00",
// "Price": 3.99,
// "Sizes": [
// "Small",
// "Medium",
// "Large"
// ]
//}
Product deserializedProduct = JsonConvert.DeserializeObject<Product>(output);
答案 3 :(得分:-1)
看看
System.Web.Script.Serialization.JavaScriptSerializer
样品
var ser = new JavaScriptSerializer();
var result = (IReadOnlyDictionary<string, object>)ser.DeserializeObject(json);
if(result["version"] == "1.0")
{
// You expect a string for result["condition"]
}
else
{
// You expect an IEnumerable<string> for result["condition"]
}