【发布时间】:2017-10-30 20:46:15
【问题描述】:
我有一些想要反序列化的 json。反序列化回列表很容易但是我正在使用接口,这就是我需要反序列化的结果:
让我们从一些 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是旧的接口/抽象类型错误:
'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);
我总是返回一个空值。
当我在我的 ConcreteConverter CanConvert/ReadJson/WriteJson 方法上设置断点时 - 它们永远不会被命中。
我缺少什么,以及如何获得以下魔力:
IList<IRootObject> MyDeserialisedObject = JsonConvert.Deserialise<IList<IRootObject>>(JsonString);
正常工作。
我必须注意,我不想只是 typnamehandling.objects(我认为就是这样),它将 ASSEMBLYNAME.TYPE 等添加到 json 中,从而使其膨胀。假设上面的 json 是我们必须使用的,上面表示的类及其接口是它必须反序列化的。
问候,
查德
PS - 我已经改变了类名/属性等,使其远离我正在做的实际现实世界的实现。因此,如果他们出现错误,我深表歉意。但希望大多数人都没事,并且理解重点/最终目标:)
【问题讨论】:
-
您可能没有发布所有代码,但是您在哪里/如何告诉 JsonConvert 使用您的自定义转换器?
-
@Camilo 我现在离开电脑了。想一想,我不确定我是否是:S 你能否发布一下你将如何做到这一点。谢谢。
-
看我的回答,可能就是你想要的
标签: c# json json.net deserialization