gpt4 book ai didi

c# - 将 JSON 反序列化为抽象类

转载 作者:IT老高 更新时间:2023-10-28 12:49:16 36 4
gpt4 key购买 nike

我正在尝试将 JSON 字符串反序列化为从抽象类继承的具体类,但我无法让它工作。我用谷歌搜索并尝试了一些解决方案,但它们似乎也不起作用。

这就是我现在拥有的:

abstract class AbstractClass { }

class ConcreteClass { }

public AbstractClass Decode(string jsonString)
{
JsonSerializerSettings jss = new JsonSerializerSettings();
jss.TypeNameHandling = TypeNameHandling.All;
return (AbstractClass)JsonConvert.DeserializeObject(jsonString, null, jss);
}

但是,如果我尝试转换生成的对象,它就不起作用。

我不使用 DeserializeObject 的原因是我有很多具体的类

有什么建议吗?

  • 我正在使用 Newtonsoft.Json

最佳答案

人们可能不想使用 TypeNameHandling(因为想要更紧凑的 json 或者想要为类型变量使用特定名称而不是“$type”)。同时,customCreationConverter approach如果想将基类反序列化为多个派生类中的任何一个,而事先不知道要使用哪个派生类,则将无法工作。

另一种方法是在基类中使用 int 或其他类型并定义 JsonConverter。

[JsonConverter(typeof(BaseConverter))]
abstract class Base
{
public int ObjType { get; set; }
public int Id { get; set; }
}

class DerivedType1 : Base
{
public string Foo { get; set; }
}

class DerivedType2 : Base
{
public string Bar { get; set; }
}

然后,基类的 JsonConverter 可以根据对象的类型反序列化对象。复杂之处在于,为了避免堆栈溢出(JsonConverter 反复调用自身),在反序列化期间必须使用自定义合约解析器。

public class BaseSpecifiedConcreteClassConverter : DefaultContractResolver
{
protected override JsonConverter ResolveContractConverter(Type objectType)
{
if (typeof(Base).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(Base));
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
switch (jo["ObjType"].Value<int>())
{
case 1:
return JsonConvert.DeserializeObject<DerivedType1>(jo.ToString(), SpecifiedSubclassConversion);
case 2:
return JsonConvert.DeserializeObject<DerivedType2>(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
}
}

就是这样。现在您可以使用序列化/反序列化任何派生类。您还可以在其他类中使用基类并序列化/反序列化它们而无需任何额外工作:

class Holder
{
public List<Base> Objects { get; set; }
}
string json = @"
[
{
""Objects"" :
[
{ ""ObjType"": 1, ""Id"" : 1, ""Foo"" : ""One"" },
{ ""ObjType"": 1, ""Id"" : 2, ""Foo"" : ""Two"" },
]
},
{
""Objects"" :
[
{ ""ObjType"": 2, ""Id"" : 3, ""Bar"" : ""Three"" },
{ ""ObjType"": 2, ""Id"" : 4, ""Bar"" : ""Four"" },
]
},
]";

List<Holder> list = JsonConvert.DeserializeObject<List<Holder>>(json);
string serializedAgain = JsonConvert.SerializeObject(list);
Debug.WriteLine(serializedAgain);

关于c# - 将 JSON 反序列化为抽象类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20995865/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com