如何使用 Json.Net 反序列化 JSON 和使用子类型的 Xamarin?
How to deserialize JSON with Json.Net and Xamarin with SubTypes?
我正在尝试反序列化这个 json:
{
"teaser": [{
"id": "...",
"type": "category",
"url": "https:...",
},{
"id": "...",
"type": "brand",
"url": "https:...",
"videoCount": 1,
},{
"id": "...",
"type": "video",
"url": "https:...",
"headline": "...",
}]
}
它有一个预告片列表,其中每个预告片都不同,具体取决于其类型。
这些将是我的对象:
public class StartPage
{
public IList<Teaser> Teaser { get; set; }
}
public abstract class Teaser
{
public string Id { get; set; }
public string Url { get; set; }
}
public class Video : Teaser
{
public string Headline { get; set; }
}
public class Brand : Teaser
{
public int VideoCount { get; set; }
}
我是 Json.NET 和 Xamarin 的新手,目前还找不到针对这种情况的解决方案。以前,当我使用 Android Studio 和 Gson 时,我可以通过以下方式注册 sybtypes:
RuntimeTypeAdapterFactory<Teaser> teaserRuntimeTypeAdapterFactory = RuntimeTypeAdapterFactory.of(
Teaser.class, "type")
.registerSubtype(Video.class, Teaser.TYPE_VIDEO)
.registerSubtype(Brand.class, Teaser.TYPE_BRAND)
.registerSubtype(Category.class, Teaser.TYPE_CATEGORY);
return new GsonBuilder()
.registerTypeAdapterFactory(teaserRuntimeTypeAdapterFactory);
有没有类似的方法来实现我想要的 Json.NET 我已经忽略了?
您可以创建自定义 JsonConverter
请在代码段下方找到 this dot net fiddle
string json ="{ 'Teaser': [{ 'id': '...', 'type': 'category', 'url': 'https:...', },{ 'id': '...', 'type': 'brand', 'url': 'https:...', 'videoCount': 1, },{ 'id': '...', 'type': 'video', 'url': 'https:...', 'headline': '...', }]}";
var list = JsonConvert.DeserializeObject<StartPage>(json);
public class BaseSpecifiedConcreteClassConverter : DefaultContractResolver
{
protected override JsonConverter ResolveContractConverter(Type objectType)
{
if (typeof(Teaser).IsAssignableFrom(objectType) && !objectType.IsAbstract)
return null; // pretend TableSortRuleConvert is not specified (thus avoiding a stack overflow)
return base.ResolveContractConverter(objectType);
}
}
public class BaseConverter : JsonConverter
{
static JsonSerializerSettings SpecifiedSubclassConversion = new JsonSerializerSettings() { ContractResolver = new BaseSpecifiedConcreteClassConverter() };
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Teaser));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
switch (jo["type"].Value<string>())
{
case "video":
return JsonConvert.DeserializeObject<Video>(jo.ToString(), SpecifiedSubclassConversion);
case "brand":
return JsonConvert.DeserializeObject<Brand>(jo.ToString(), SpecifiedSubclassConversion);
default:
throw new Exception();
}
throw new NotImplementedException();
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException(); // won't be called because CanWrite returns false
}
}
随意在 switch case
硬代码中创建自定义逻辑 class name 可能不是一个好主意,而是创建 enum
或类似的东西,但这是实现此类场景的方法
我正在尝试反序列化这个 json:
{
"teaser": [{
"id": "...",
"type": "category",
"url": "https:...",
},{
"id": "...",
"type": "brand",
"url": "https:...",
"videoCount": 1,
},{
"id": "...",
"type": "video",
"url": "https:...",
"headline": "...",
}]
}
它有一个预告片列表,其中每个预告片都不同,具体取决于其类型。 这些将是我的对象:
public class StartPage
{
public IList<Teaser> Teaser { get; set; }
}
public abstract class Teaser
{
public string Id { get; set; }
public string Url { get; set; }
}
public class Video : Teaser
{
public string Headline { get; set; }
}
public class Brand : Teaser
{
public int VideoCount { get; set; }
}
我是 Json.NET 和 Xamarin 的新手,目前还找不到针对这种情况的解决方案。以前,当我使用 Android Studio 和 Gson 时,我可以通过以下方式注册 sybtypes:
RuntimeTypeAdapterFactory<Teaser> teaserRuntimeTypeAdapterFactory = RuntimeTypeAdapterFactory.of(
Teaser.class, "type")
.registerSubtype(Video.class, Teaser.TYPE_VIDEO)
.registerSubtype(Brand.class, Teaser.TYPE_BRAND)
.registerSubtype(Category.class, Teaser.TYPE_CATEGORY);
return new GsonBuilder()
.registerTypeAdapterFactory(teaserRuntimeTypeAdapterFactory);
有没有类似的方法来实现我想要的 Json.NET 我已经忽略了?
您可以创建自定义 JsonConverter
请在代码段下方找到 this dot net fiddle
string json ="{ 'Teaser': [{ 'id': '...', 'type': 'category', 'url': 'https:...', },{ 'id': '...', 'type': 'brand', 'url': 'https:...', 'videoCount': 1, },{ 'id': '...', 'type': 'video', 'url': 'https:...', 'headline': '...', }]}";
var list = JsonConvert.DeserializeObject<StartPage>(json);
public class BaseSpecifiedConcreteClassConverter : DefaultContractResolver
{
protected override JsonConverter ResolveContractConverter(Type objectType)
{
if (typeof(Teaser).IsAssignableFrom(objectType) && !objectType.IsAbstract)
return null; // pretend TableSortRuleConvert is not specified (thus avoiding a stack overflow)
return base.ResolveContractConverter(objectType);
}
}
public class BaseConverter : JsonConverter
{
static JsonSerializerSettings SpecifiedSubclassConversion = new JsonSerializerSettings() { ContractResolver = new BaseSpecifiedConcreteClassConverter() };
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Teaser));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
switch (jo["type"].Value<string>())
{
case "video":
return JsonConvert.DeserializeObject<Video>(jo.ToString(), SpecifiedSubclassConversion);
case "brand":
return JsonConvert.DeserializeObject<Brand>(jo.ToString(), SpecifiedSubclassConversion);
default:
throw new Exception();
}
throw new NotImplementedException();
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException(); // won't be called because CanWrite returns false
}
}
随意在 switch case
硬代码中创建自定义逻辑 class name 可能不是一个好主意,而是创建 enum
或类似的东西,但这是实现此类场景的方法