gpt4 book ai didi

c# - 在 JSON.NET 中反序列化 IList

转载 作者:行者123 更新时间:2023-11-30 14:23:41 24 4
gpt4 key购买 nike

我有一些我想要反序列化的 json。反序列化回列表非常容易但是我正在使用接口(interface),这就是我需要反序列化以结束:

所以让我们从一些 JSON 开始:

[{"TimeGenerated":"2017-05-30T19:21:06.5331472+10:00","OuterValue":1.08,"Identifier":{"IdentifierName":"BLA","IdentifierNumber":1},"Locale":{"LocaleName":"LOCALE NAME","LocaleType":1,"LocaleNumber":1,"StartTime":"2017-05-30T19:20:00+10:00"},"InnerValue":1.08,"InnerType":0,"InnerId":"InnerI","Type":"MyType","Id":"11111"}]

这是在服务器端序列化的数据(当然没有问题),它的对象类型是:

IList<IRootObject>

如此有效,我想将另一端反序列化为:

IList<IRootObject> MyDeserialisedObject = JsonConvert.Deserialise<IList<IRootObject>>(JsonString);

显然这里的 pickle 是旧的接口(interface)/抽象类型错误:

'Could not create an instance of type BLA. Type is an interface or abstract class and cannot be instantiated'

好吧,我创建了一些自定义转换器并装饰如下:

类是:

    [JsonObject(MemberSerialization.OptIn)]
public class Identifier
{
[JsonProperty]
public string IdentifierName { get; set; }
[JsonProperty]
public int IdentifierNumber { get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public class Locale
{
[JsonProperty]
public string LocaleName { get; set; }
[JsonProperty]
public int LocaleType { get; set; }
[JsonProperty]
public int LocaleNumber { get; set; }
[JsonProperty]
public string StartTime { get; set; }
}

[JsonObject(MemberSerialization.OptIn)]
public class RootObject:IRootObject
{
[JsonProperty]
public string TimeGenerated { get; set; }
[JsonProperty]
public double OuterValue { get; set; }
[JsonProperty]
[JsonConverter(typeof(ConcreteConverter<Identifier>))]
public IIdentifier Identifier { get; set; }
[JsonProperty]
[JsonConverter(typeof(ConcreteConverter<Locale>))]
public ILocale Locale { get; set; }
[JsonProperty]
public double InnerValue { get; set; }
[JsonProperty]
public int InnerType { get; set; }
[JsonProperty]
public string InnerId { get; set; }
[JsonProperty]
public string Type { get; set; }
[JsonProperty]
public string Id { get; set; }
}

界面是:

public interface IRootObject
{
string TimeGenerated { get; set; }
double OuterValue { get; set; }
Identifier Identifier { get; set; }
Locale Locale { get; set; }
double InnerValue { get; set; }
int InnerType { get; set; }
string InnerId { get; set; }
string Type { get; set; }
string Id { get; set; }
}

具体转换器如下:

public class ConcreteConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
try
{
var s = serializer.Deserialize<T>(reader);
return s;
}
catch (Exception ex)
{
return null;
}
// return serializer.Deserialize<T>(reader);
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}

我还有一个我制作的列表转换器(看到这是一个列表,尽管它未被使用,但这里需要 JIC):

public class ConcreteListConverter<TInterface, TImplementation> : JsonConverter where TImplementation : TInterface
{
public override bool CanConvert(Type objectType)
{
return true;
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (existingValue == null)
return null;

var res = serializer.Deserialize<List<TImplementation>>(reader);
return res.ConvertAll(x => (TInterface)x);
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);

}

所以问题是:

当我运行时:

IList<IRootObject> MyDeserialisedObject = JsonConvert.Deserialise<IList<IRootObject>>(JsonString);

我总是返回 null。

当我在我的 ConcreteConverter CanConvert/ReadJson/WriteJson 方法上放置断点时 - 它们永远不会被击中。

我错过了什么,我如何获得魔力:

IList<IRootObject> MyDeserialisedObject = JsonConvert.Deserialise<IList<IRootObject>>(JsonString);

正常工作。

我必须注意,我不想只在 typnamehandling.objects(我认为就是它)中将 ASSEMBLYNAME.TYPE 等添加到 json 中,从而使其膨胀。假设上面的 json 是我们必须处理的,上面表示的类及其接口(interface)是必须反序列化的。

问候,

查德

PS - 我已经更改了类名/属性等,使其远离我正在做的事情的实际实现。因此,如果他们出现错误,我深表歉意。但希望大多数人都没事,并且理解要点/最终目标:)

最佳答案

问题

您不能创建接口(interface)的实例,这在 .NET 中是不允许的。你不能这样做:

var items = new IList<int>(); // Not allowed

您的错误明确指出:

Could not create an instance of type BLA. Type is an interface or abstract class and cannot be instantiated'

解决方案

将其反序列化为 List 类型,但将其分配给 IList 类型。请注意右侧的类型不是下面代码中的接口(interface),除了在转换阶段。

IList<IRootObject> MyDeserialisedObject = 
JsonConvert.DeserializeObject<List<RootObject>>(File.ReadAllText(JsonString))
.Cast<IRootObject>().ToList();

更多的麻烦

您可能会问“为什么我需要转换”,为什么我不能这样做呢?

IList<IRootObject> MyDeserialisedObject = 
JsonConvert.DeserializeObject<List<RootObject>>(File.ReadAllText(JsonString));

这是不允许的 preserve reference identity .

关于c# - 在 JSON.NET 中反序列化 IList<Interface>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44261170/

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