- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前面临的情况是,我得到了一个我无法修改的 json 文件,我希望生成的反序列化类对于设计目的是通用的。
首先是我的界面:
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 class ThumbnailJobModel : IJobModel
{
[JsonProperty( "clientBaseURL" )]
public string ClientBaseURL { get; set; }
[JsonProperty( "userEmail" )]
public string UserEmail { get; set; }
[JsonProperty( "type" )]
[JsonConverter( typeof( TypeConverter ) )]
public ExportType Type { get; set; }
[JsonProperty( "items" )]
[JsonConverter( typeof( ConcreteConverter<List<IItemModel>, List<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" )]
//[JsonConverter( typeof( CamSettingsConverter ) )]
[JsonConverter( typeof( ConcreteConverter<List<ICamSettings>,
List<ShootSettings>> ) )]
public List<ICamSettings> CamSettings { get; set; }
public Item()
{
CamSettings = new List<ICamSettings>();
}
}
public class ShootSettings : ICamSettings
{
[JsonProperty( "orientation" )]
[JsonConverter( typeof( OrientationConverter ) )]
public Orientation Orientation { get; set; }
[JsonProperty( "clothShape" )]
[JsonConverter( typeof( ClothShapeConverter ) )]
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<I, T> : JsonConverter
{
public override bool CanConvert( Type objectType )
{
return typeof( I ) == objectType;
}
public override object ReadJson( JsonReader reader,
Type objectType, object existingValue, JsonSerializer serializer )
{
return serializer.Deserialize<T>( reader );
}
public override void WriteJson( JsonWriter writer,
object value, JsonSerializer serializer )
{
throw new NotImplementedException();
}
}
public class OrientationConverter : JsonConverter
{
public override object ReadJson( JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer )
{
string enumString = (string)reader.Value;
return Enum.Parse( typeof( Orientation ), enumString, true );
}
public override bool CanConvert( Type objectType )
{
return objectType == typeof( string );
}
public override void WriteJson( JsonWriter writer, object value,
JsonSerializer serializer )
{
throw new NotImplementedException();
}
}
public class ClothShapeConverter : JsonConverter
{
public override object ReadJson( JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer )
{
var enumString = (string)reader.Value;
return Enum.Parse( typeof( Shape ), enumString, true );
}
public override bool CanConvert( Type objectType )
{
return objectType == typeof( string );
}
public override void WriteJson( JsonWriter writer, object value,
JsonSerializer serializer )
{
throw new NotImplementedException();
}
}
public class TypeConverter : JsonConverter
{
public override object ReadJson( JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer )
{
return ExportType.Thumbnails;
}
public override bool CanConvert( Type objectType )
{
return objectType == typeof( string );
}
public override void WriteJson( JsonWriter writer, object value,
JsonSerializer serializer )
{
throw new NotImplementedException();
}
}
public static void HandleDeserializationError( object sender,
ErrorEventArgs errorArgs )
{
errorArgs.ErrorContext.Handled = true;
var currentObj = errorArgs.CurrentObject as ShootSettings;
if ( currentObj == null ) return;
currentObj.Orientation = Orientation.Perspective;
currentObj.Shape = Shape.Folded;
}
}
如您所见,IItemModel
界面中有一个ICamSettings
列表。
我尝试将此 json 反序列化到我的 ThumbnailJobModel
类中:
{
"clientBaseURL":"https://clientName.fr",
"userEmail":"myName@gmail.com",
"items":[
{
"id":"11913",
"imageSize":"1280,720",
"imagePpi":"72",
"shoots":[
{
"fileName":"front1.png",
"orientation":"front",
"clothShape":"hanger"
},
{
"fileName":"folded1.png",
"orientation":"front",
"clothShape":"folded"
},
{
"fileName":"right1.png",
"orientation":"right",
"clothShape":"hanger"
}
]
},
{
"id":"2988",
"imageSize":"1280,720",
"imagePpi":"",
"shoots":[
{
"fileName":"perspective1.png",
"orientation":"perspective"
}
]
}
]
}
我这样反序列化我的 json :
//Read the job config
string jobConfig = File.ReadAllText( jsonConfigPath );
IJobModel m_jobModel = JsonConvert.DeserializeObject<ThumbnailJobModel>(
jobConfig );
并抛出以下异常:
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
老实说,我不明白我做错了什么,我希望有人能够对此有所启发。
最佳答案
你的基本问题是你的 ConcreteConverter<I, T>
旨在将声明为接口(interface)的内容反序列化为具体类型——例如IItemModel
作为Item
- 但你没有以那种方式使用它。您正在使用它将具体的接口(interface)列表反序列化为具体类型的具体列表,例如:
[JsonProperty( "items" )]
[JsonConverter( typeof( ConcreteConverter<List<IItemModel>, List<Item>>) )]
public List<IItemModel> Items { get; set; }
相反,您应该将转换器应用于 Items
的项目和 CamSettings
使用 JsonPropertyAttribute.ItemConverterType
的集合像这样:
public class ThumbnailJobModel : IJobModel
{
[JsonProperty("items", ItemConverterType = typeof(ConcreteConverter<IItemModel, Item>))]
public List<IItemModel> Items { get; set; }
和
public class Item : IItemModel
{
[JsonProperty("shoots", ItemConverterType = typeof(ConcreteConverter<ICamSettings, ShootSettings>))]
public List<ICamSettings> CamSettings { get; set; }
这应该可以修复异常。但是,还有其他建议:
在几个转换器中,您没有实现 WriteJson()
.如果你想使用默认序列化,你可以override CanWrite
and return false
.
请重命名 TypeConverter
至 ExportTypeConverter
. TypeConverter
已用于 something else .
OrientationConverter
和 ClothShapeConverter
是不必要的,内置的 StringEnumConverter
会将任何枚举序列化和反序列化为字符串。
如果您希望为数字枚举值抛出异常,您可以将其子类化为 StrictStringEnumConverter
并设置 AllowIntegerValues = false
:
public class StrictStringEnumConverter : StringEnumConverter
{
public StrictStringEnumConverter() { this.AllowIntegerValues = false; }
}
你也可以制作ExportTypeConverter
继承自 StringEnumConverter
以获得所需的序列化行为。
在 ConcreteConverter
自 T
应该是 I
的具体实现, 你可以添加一个 where
确保该类型的用户不会意外反转通用参数的约束:
public class ConcreteConverter<IInterface, TConcrete> : JsonConverter where TConcrete : IInterface
{
}
我还将通用参数重命名为更有意义的内容。
在几个转换器中,您覆盖了 CanConvert(Type)
并测试传入类型是 string
, 其中string
是序列化到文件的类型:
public override bool CanConvert( Type objectType )
{
return objectType == typeof( string );
}
当直接由属性应用时,CanConvert()
永远不会被调用。当通过设置应用时,在序列化期间 objectType
是即将被序列化的对象的实际类型。当通过设置应用时,在反序列化过程中 objectType
是其值即将被反序列化的成员的声明类型。它永远不是文件中的类型。因此在 ExportTypeConverter
应该这样写:
public override bool CanConvert(Type objectType)
{
return objectType == typeof(ExportType);
}
或者,由于转换器仅适用于属性,您可以抛出 NotImplementedException
.
我看不出有任何理由嵌套像 Item
这样的模型里面ThumbnailJobModel
.对我来说,这只会导致额外的复杂性。您可以改为将它们设为非公开。但这只是见仁见智。
将所有这些放在一起,您的代码应该类似于:
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;
}
}
sample 加工 .Net fiddle .
关于c# - 当具体类包含其他接口(interface)时如何反序列化接口(interface)集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47939878/
我正在尝试在我的代码库中为我正在编写的游戏服务器更多地使用接口(interface),并了解高级概念以及何时应该使用接口(interface)(我认为)。在我的例子中,我使用它们将我的包相互分离,并使
我有一个名为 Widget 的接口(interface),它在我的整个项目中都在使用。但是,它也用作名为 Widget 的组件的 Prop 。 处理此问题的最佳方法是什么?我应该更改我的 Widget
有一个接口(interface)可以是多个接口(interface)之一 interface a {x:string} interface b {y:string} interface c {z:st
我遇到了一种情况,我需要调用第三方服务来获取一些信息。这些服务对于不同的客户可能会有所不同。我的界面中有一个身份验证功能,如下所示。 interface IServiceProvider { bool
在我的例子中,“RequestHandlerProxy”是一个结构,其字段为接口(interface)“IAdapter”,接口(interface)有可能被调用的方法,该方法的输入为结构“Reque
我有一个接口(interface)Interface1,它已由类A实现,并且设置了一些私有(private)变量值,并且我将类A的对象发送到下一个接受输入作为Interface2的类。那么我怎样才能将
假设我有这样的类和接口(interface)结构: interface IService {} interface IEmailService : IService { Task SendAs
有人知道我在哪里可以找到 XML-RPC 接口(interface)的定义(在 OpenERP 7 中)?我想知道创建或获取对象需要哪些参数和对象属性。每个元素的 XML 示例也将非常有帮助。 最佳答
最近,我一直在阅读有关接口(interface)是抽象的错误概念的文章。一篇这样的帖子是http://blog.ploeh.dk/2010/12/02/InterfacesAreNotAbstract
如果我有一个由第三方实现的现有 IInterface 后代,并且我想添加辅助例程,Delphi 是否提供了任何简单的方法来实现此目的,而无需手动重定向每个接口(interface)方法?也就是说,给定
我正在尝试将 Article 数组分配给我的 Mongoose 文档,但 Typescript 似乎不喜欢这样,我不知道为什么它显示此警告/错误,表明它不可分配. 我的 Mongoose 模式和接口(
我有两个接口(interface): public interface IController { void doSomething(IEntity thing); } public inte
是否可以创建一个扩展 Serializable 接口(interface)的接口(interface)? 如果是,那么扩展接口(interface)的行为是否会像 Serilizable 接口(int
我试图在两个存储之间创建一个中间层,它从存储 A 中获取数据,将其转换为相应类型的存储 B,然后存储它。由于我需要转换大约 50-100 种类型,我希望使用 map[string]func 并根据 s
我正在处理一个要求,其中我收到一个 JSON 对象,其中包含一个日期值作为字符串。我的任务是将 Date 对象存储在数据库中。 这种东西: {"start_date": "2019-05-29", "
我们的方法的目标是为我们现有的 DAO 和模型类引入接口(interface)。模型类由各种类型的资源 ID 标识,资源 ID 不仅仅是随机数,还带有语义和行为。因此,我们必须用对象而不是原始类型来表
Collection 接口(interface)有多个方法。 List 接口(interface)扩展了 Collection 接口(interface)。它声明与 Collection 接口(int
我有一个 Java 服务器应用程序,它使用 Jackson 使用反射 API 对 DTO 进行一般序列化。例如对于这个 DTO 接口(interface): package com.acme.libr
如果我在 Kotlin 中有一个接口(interface): interface KotlinInterface { val id: String } 我可以这样实现: class MyCla
我知道Java中所有访问修饰符之间的区别。然而,有人问了我一个非常有趣的问题,我很难找到答案:Java 中的 private 接口(interface)和 public 接口(interface)有什
我是一名优秀的程序员,十分优秀!