Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当具体类包含其他接口时,如何反序列化接口集合_C#_Json.net_Deserialization - Fatal编程技术网

C# 当具体类包含其他接口时,如何反序列化接口集合

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

我目前面临的情况是,我得到了一个无法修改的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; }
}
我将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
as
Item
,但您并没有以这种方式使用它。您正在使用它将接口的具体列表反序列化为具体类型的具体列表,例如:

[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;
        }
    }