我正在编写一个应用程序,它获取一个Json对象列表,如下所示:
[
{
"ObjectType": "apple",
"ObjectSize": 35,
"ObjectCost": 4,
"ObjectTaste": "good",
"ObjectColor": "golden"
},
{
"ObjectType": "books",
"ObjectSize": 53,
"ObjectCost": 7,
"Pages": 100
},
{
"ObjectType": "melon",
"ObjectSize": 35,
"ObjectTaste": "good",
"ObjectCost": 5
},
{
"ObjectType": "apple",
"ObjectSize": 29,
"ObjectCost": 8,
"ObjectTaste": "almost good",
"ObjectColor": "red"
}
]我想要做一个基类ItemToSell (大小,成本),并从它派生苹果,甜瓜和图书,然后使反序列化基于"ObjectType“字段的任何类适合。我希望它构建一个ItemToSell对象列表,每个对象都是苹果、瓜或书籍。
我怎么能在.Net上做到这一点?
(预先谢谢:)
编辑:我知道如何在一个Big中反序列化它,它可以包含的所有字段,比如:Base(ObjectType,ObjectSize,ObjectCost,ObjectColor,Pages)。但是我希望它通过ObjectType来区分类,这样我就不会有任何有用的字段,比如每个图书条目的页面字段,或者每本书的ObjectTaste字段。
发布于 2014-05-09 14:41:19
不久前我也遇到了同样的问题。
您可以使用Json.NET,但如果您无法控制json文档(如:“它已被其他框架序列化”),则需要创建如下所示的自定义JsonConverter:
class MyItemConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(ItemToSell).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
string discriminator = (string)obj["ObjectType"];
ItemToSell item;
switch (discriminator)
{
case "apple":
item = new Apple();
break;
case "books":
item = new Books();
break;
case "melon":
item = new Melon();
break;
default:
throw new NotImplementedException();
}
serializer.Populate(obj.CreateReader(), item);
return item;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
}
}然后需要将它添加到JsonSerializerSettings的转换器中,如下所示:
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Objects,
};
settings.Converters.Add(new MyItemConverter());
var items = JsonConvert.DeserializeObject<List<ItemToSell>>(response, settings);发布于 2014-05-09 14:45:35
您可以使用CustomCreationConverter。这使您可以连接到反序列化过程。
public abstract class Base
{
public string Type { get; set; }
}
class Foo : Base
{
public string FooProperty { get; set; }
}
class Bar : Base
{
public string BarProperty { get; set; }
}
class CustomSerializableConverter : CustomCreationConverter<Base>
{
public override Base Create(Type objectType)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
var type = (string)jObject.Property("Type");
Base target;
switch (type)
{
case "Foo":
target = new Foo();
break;
case "Bar":
target = new Bar();
break;
default:
throw new InvalidOperationException();
}
serializer.Populate(jObject.CreateReader(), target);
return target;
}
}
class Program
{
static void Main(string[] args)
{
var json = "[{Type:\"Foo\",FooProperty:\"A\"},{Type:\"Bar\",BarProperty:\"B\"}]";
List<Base> bases = JsonConvert.DeserializeObject<List<Base>>(json, new CustomSerializableConverter());
}
}发布于 2014-05-09 14:43:45
这不是一个答案,但在C# 6.0中,您可以这样做:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;
[TestMethod]
public void JsonWithDollarOperatorStringIndexers()
{
// Additional data types eliminated for elucidation
string jsonText = @"
{
'Byte': {
'Keyword': 'byte',
'DotNetClassName': 'Byte',
'Description': 'Unsigned integer',
'Width': '8',
'Range': '0 to 255'
},
'Boolean': {
'Keyword': 'bool',
'DotNetClassName': 'Boolean',
'Description': 'Logical Boolean type',
'Width': '8',
'Range': 'True or false.'
},
}";
JObject jObject = JObject.Parse(jsonText);
Assert.AreEqual("bool", jObject.$Boolean.$Keyword);
}取自这里。
https://stackoverflow.com/questions/23566980
复制相似问题