C# 当具体类包含其他接口时,如何反序列化接口集合
我目前面临的情况是,我得到了一个无法修改的json文件,我希望得到的反序列化类在设计上是通用的 首先是我的界面:C# 当具体类包含其他接口时,如何反序列化接口集合,c#,json.net,deserialization,C#,Json.net,Deserialization,我目前面临的情况是,我得到了一个无法修改的json文件,我希望得到的反序列化类在设计上是通用的 首先是我的界面: public interface IJobModel { string ClientBaseURL { get; set; } string UserEmail { get; set; } ExportType Type { get; set; } List<IItemModel> Items { get; set; } } public
public interface IJobModel
{
string ClientBaseURL { get; set; }
string UserEmail { get; set; }
ExportType Type { get; set; }
List<IItemModel> Items { get; set; }
}
public interface IItemModel
{
string Id { get; set; }
string ImageSize { get; set; }
string ImagePpi { get; set; }
List<ICamSettings> CamSettings { get; set; }
}
public interface ICamSettings
{
string FileName { get; set; }
}
我将json反序列化如下:
//Read the job config
string jobConfig = File.ReadAllText( jsonConfigPath );
IJobModel m_jobModel = JsonConvert.DeserializeObject<ThumbnailJobModel>(
jobConfig );
//读取作业配置
字符串jobConfig=File.ReadAllText(jsonConfigPath);
IJobModel m_jobModel=JsonConvert.DeserializeObject(
作业配置);
并引发以下异常:
Exception : Error setting value to 'CamSettings' on
'IWD.Screenshoter.Job.ThumbnailJobModel+Item'.
Stack :
at Newtonsoft.Json.Serialization.DynamicValueProvider.SetValue
(System.Object target, System.Object value) [0x00000] in <filename
unknown>:0
at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue
(Newtonsoft.Json.Serialization.JsonProperty property,
Newtonsoft.Json.JsonConverter propertyConverter,
Newtonsoft.Json.Serialization.JsonContainerContract containerContract,
Newtonsoft.Json.Serialization.JsonProperty containerProperty,
Newtonsoft.Json.JsonReader reader, System.Object target) [0x00000] in
<filename unknown>:0
at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject
(System.Object newObject, Newtonsoft.Json.JsonReader reader,
Newtonsoft.Json.Serialization.JsonObjectContract contract,
Newtonsoft.Json.Serialization.JsonProperty member, System.String id)
[0x00000] in <filename unknown>:0
异常:将值设置为“CamSettings”时出错
'IWD.Screenshoter.Job.ThumbnailJobModel+项目'。
堆栈:
位于Newtonsoft.Json.Serialization.DynamicValueProvider.SetValue
(System.Object目标,System.Object值)[0x00000]输入:0
在
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue
(Newtonsoft.Json.Serialization.JsonProperty属性,
Newtonsoft.Json.Json转换器属性转换器,
Newtonsoft.Json.Serialization.JsonContainerContract集装箱合同,
Newtonsoft.Json.Serialization.JsonProperty containerProperty,
Newtonsoft.Json.JsonReader读取器,System.Object目标)[0x00000]位于
:0
在
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject
(System.Object newObject、Newtonsoft.Json.JsonReader、,
Newtonsoft.Json.Serialization.jsonObject合同,
Newtonsoft.Json.Serialization.JsonProperty成员,System.String id)
[0x00000]英寸:0
我真的不明白我做错了什么,我希望有人能对此有所了解。您的基本问题是您的
ConcreteConverter
旨在将声明为接口的内容反序列化为具体类型,例如IItemModel
asItem
,但您并没有以这种方式使用它。您正在使用它将接口的具体列表反序列化为具体类型的具体列表,例如:
[JsonProperty( "items" )]
[JsonConverter( typeof( ConcreteConverter<List<IItemModel>, List<Item>>) )]
public List<IItemModel> Items { get; set; }
及
您还可以使ExportTypeConverter
从StringEnumConverter
继承,以获得所需的序列化行为
ConcreteConverter
中,由于T
被认为是I
的具体实现,因此可以在其中添加约束,以确保该类型的用户不会意外反转泛型参数:
public class ConcreteConverter<IInterface, TConcrete> : JsonConverter where TConcrete : IInterface
{
}
当通过属性直接应用时,永远不会调用CanConvert()
。当通过设置应用时,在序列化期间objectType
是将要序列化的对象的实际类型。当通过设置应用时,在反序列化过程中,objectType是其值将被反序列化的成员的声明类型。它从来不是文件中的类型。因此,在ExportTypeConverter
中,应按如下方式编写:
public override bool CanConvert(Type objectType)
{
return objectType == typeof(ExportType);
}
或者,由于转换器仅由属性应用,因此您可以抛出一个NotImplementedException
ThumbnailJobModel
中嵌套类似Item
的模型。对我来说,这只会增加复杂性。你可以把它们变成非公开的。但这只是一个意见问题public interface IJobModel
{
string ClientBaseURL { get; set; }
string UserEmail { get; set; }
ExportType Type { get; set; }
List<IItemModel> Items { get; set; }
}
public interface IItemModel
{
string Id { get; set; }
string ImageSize { get; set; }
string ImagePpi { get; set; }
List<ICamSettings> CamSettings { get; set; }
}
public interface ICamSettings
{
string FileName { get; set; }
}
public enum ExportType
{
Thumbnails,
}
public class ThumbnailJobModel : IJobModel
{
[JsonProperty("clientBaseURL")]
public string ClientBaseURL { get; set; }
[JsonProperty("userEmail")]
public string UserEmail { get; set; }
[JsonProperty("type")]
[JsonConverter(typeof(ExportTypeConverter))]
public ExportType Type { get; set; }
[JsonProperty("items", ItemConverterType = typeof(ConcreteConverter<IItemModel, Item>))]
public List<IItemModel> Items { get; set; }
public ThumbnailJobModel()
{
Type = ExportType.Thumbnails;
Items = new List<IItemModel>();
}
public class Item : IItemModel
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("imageSize")]
public string ImageSize { get; set; }
[JsonProperty("imagePpi")]
public string ImagePpi { get; set; }
[JsonProperty("shoots", ItemConverterType = typeof(ConcreteConverter<ICamSettings, ShootSettings>))]
public List<ICamSettings> CamSettings { get; set; }
public Item()
{
CamSettings = new List<ICamSettings>();
}
}
public class ShootSettings : ICamSettings
{
[JsonProperty("orientation")]
[JsonConverter(typeof(StrictStringEnumConverter))]
public Orientation Orientation { get; set; }
[JsonProperty("clothShape")]
[JsonConverter(typeof(StrictStringEnumConverter))]
public Shape Shape { get; set; }
[JsonProperty("fileName")]
public string FileName { get; set; }
public ShootSettings()
{
Orientation = Orientation.Perspective;
Shape = Shape.Folded;
FileName = null;
}
}
public enum Orientation
{
Perspective = 0,
Oblique = 1,
Front = 2,
Back = 3,
Left = 4,
Right = 5,
Up = 6,
Down = 7
}
public enum Shape
{
Folded = 0,
Hanger = 1,
Mannequin = 2
}
public class ConcreteConverter<IInterface, TConcrete> : JsonConverter where TConcrete : IInterface
{
public override bool CanConvert(Type objectType)
{
return typeof(IInterface) == objectType;
}
public override object ReadJson(JsonReader reader,
Type objectType, object existingValue, JsonSerializer serializer)
{
return serializer.Deserialize<TConcrete>(reader);
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public class ExportTypeConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
reader.Skip(); // Skip anything at the current reader's position.
return ExportType.Thumbnails;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(ExportType);
}
}
public class StrictStringEnumConverter : StringEnumConverter
{
public StrictStringEnumConverter() { this.AllowIntegerValues = false; }
}
public static void HandleDeserializationError(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs errorArgs)
{
errorArgs.ErrorContext.Handled = true;
var currentObj = errorArgs.CurrentObject as ShootSettings;
if (currentObj == null) return;
currentObj.Orientation = Orientation.Perspective;
currentObj.Shape = Shape.Folded;
}
}
公共接口模型
{
字符串ClientBaseURL{get;set;}
字符串UserEmail{get;set;}
ExportType类型{get;set;}
列表项{get;set;}
}
公共接口项目模型
{
字符串Id{get;set;}
字符串ImageSize{get;set;}
字符串ImagePpi{get;set;}
列表设置{get;set;}
}
公共接口ICAM设置
{
字符串文件名{get;set;}
}
公共枚举导出类型
{
缩略图,
}
公共类ThumbnailJobModel:IJobModel
{
[JsonProperty(“clientBaseURL”)]
公共字符串ClientBaseURL{get;set;}
[JsonProperty(“用户电子邮件”)]
公共字符串UserEmail{get;set;}
[JsonProperty(“类型”)]
[JsonConverter(typeof(ExportTypeConverter))]
公共导出类型类型{get;set;}
[JsonProperty(“items”,ItemConverterType=typeof(ConcreteConverter))]
公共列表项{get;set;}
公共ThumbnailJobModel()
{
类型=导出类型。缩略图;
项目=新列表();
}
公共类项:IItemModel
{
[JsonProperty(“id”)]
公共字符串Id{get;set;}
[JsonProperty(“imageSize”)]
公共字符串ImageSize{get;set;}
[JsonProperty(“imagePpi”)]
公共字符串ImagePpi{get;set;}
[JsonProperty(“shoots”,ItemConverterType=typeof(ConcreteConverter))]
公共列表设置{get;set;}
公共项目()
{
CamSettings=新列表();
}
}
公共类设置:ICAM设置
{
[JsonProperty(“方向”)]
[JsonConverter(typeof(StrictStringEnumConverter))]
公共定向{get;set;}
[JsonProperty(“clothShape”)]
[JsonConverter(typeof(StrictStringEnumConverter))]
公共形状{get;set;}
[JsonProperty(“文件名”)]
公共字符串文件名{get;set;}
公共设置()
{
方向=方向。透视;
形状=形状。折叠;
FileName=null;
}
}
面向公共枚举
{
透视图=0,
倾斜=1,
正面=2,
后退=3,
左=4,
右=5,
上升=6,
向下=7
}
公共枚举形状
{
折叠=0,
吊架=1,
人体模型=2
}
公共类Concrete Converter:JsonConverter,其中TConcrete:IInterface
{
公共覆盖布尔CanConvert(类型objectType)
{
返回typeof(IInterface)==objectType;
}
公共重写对象ReadJson(JsonReader,
类型objectType、对象existingValue、JsonSerializ
public class Item : IItemModel
{
[JsonProperty("shoots", ItemConverterType = typeof(ConcreteConverter<ICamSettings, ShootSettings>))]
public List<ICamSettings> CamSettings { get; set; }
public class StrictStringEnumConverter : StringEnumConverter
{
public StrictStringEnumConverter() { this.AllowIntegerValues = false; }
}
public class ConcreteConverter<IInterface, TConcrete> : JsonConverter where TConcrete : IInterface
{
}
public override bool CanConvert( Type objectType )
{
return objectType == typeof( string );
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(ExportType);
}
public interface IJobModel
{
string ClientBaseURL { get; set; }
string UserEmail { get; set; }
ExportType Type { get; set; }
List<IItemModel> Items { get; set; }
}
public interface IItemModel
{
string Id { get; set; }
string ImageSize { get; set; }
string ImagePpi { get; set; }
List<ICamSettings> CamSettings { get; set; }
}
public interface ICamSettings
{
string FileName { get; set; }
}
public enum ExportType
{
Thumbnails,
}
public class ThumbnailJobModel : IJobModel
{
[JsonProperty("clientBaseURL")]
public string ClientBaseURL { get; set; }
[JsonProperty("userEmail")]
public string UserEmail { get; set; }
[JsonProperty("type")]
[JsonConverter(typeof(ExportTypeConverter))]
public ExportType Type { get; set; }
[JsonProperty("items", ItemConverterType = typeof(ConcreteConverter<IItemModel, Item>))]
public List<IItemModel> Items { get; set; }
public ThumbnailJobModel()
{
Type = ExportType.Thumbnails;
Items = new List<IItemModel>();
}
public class Item : IItemModel
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("imageSize")]
public string ImageSize { get; set; }
[JsonProperty("imagePpi")]
public string ImagePpi { get; set; }
[JsonProperty("shoots", ItemConverterType = typeof(ConcreteConverter<ICamSettings, ShootSettings>))]
public List<ICamSettings> CamSettings { get; set; }
public Item()
{
CamSettings = new List<ICamSettings>();
}
}
public class ShootSettings : ICamSettings
{
[JsonProperty("orientation")]
[JsonConverter(typeof(StrictStringEnumConverter))]
public Orientation Orientation { get; set; }
[JsonProperty("clothShape")]
[JsonConverter(typeof(StrictStringEnumConverter))]
public Shape Shape { get; set; }
[JsonProperty("fileName")]
public string FileName { get; set; }
public ShootSettings()
{
Orientation = Orientation.Perspective;
Shape = Shape.Folded;
FileName = null;
}
}
public enum Orientation
{
Perspective = 0,
Oblique = 1,
Front = 2,
Back = 3,
Left = 4,
Right = 5,
Up = 6,
Down = 7
}
public enum Shape
{
Folded = 0,
Hanger = 1,
Mannequin = 2
}
public class ConcreteConverter<IInterface, TConcrete> : JsonConverter where TConcrete : IInterface
{
public override bool CanConvert(Type objectType)
{
return typeof(IInterface) == objectType;
}
public override object ReadJson(JsonReader reader,
Type objectType, object existingValue, JsonSerializer serializer)
{
return serializer.Deserialize<TConcrete>(reader);
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public class ExportTypeConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
reader.Skip(); // Skip anything at the current reader's position.
return ExportType.Thumbnails;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(ExportType);
}
}
public class StrictStringEnumConverter : StringEnumConverter
{
public StrictStringEnumConverter() { this.AllowIntegerValues = false; }
}
public static void HandleDeserializationError(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs errorArgs)
{
errorArgs.ErrorContext.Handled = true;
var currentObj = errorArgs.CurrentObject as ShootSettings;
if (currentObj == null) return;
currentObj.Orientation = Orientation.Perspective;
currentObj.Shape = Shape.Folded;
}
}