C# 将Json反序列化为具体类

C# 将Json反序列化为具体类,c#,json,json-deserialization,C#,Json,Json Deserialization,在尝试反序列化Json时,我无法找到解决错误的方法: '无法创建类型为ConsoleApp1.IDisplayInstructions的实例。类型是接口或抽象类,无法实例化。路径'displayInstructions.AGB',第4行,位置34' 我理解它背后的含义;我需要指示Json反序列化器为接口成员使用哪个具体类。我只是不知道怎么做。我尝试使用JsonConstructor属性,或使用自定义反序列化程序,但两种方法都无法工作 还有一个类似的问题(),但这是一个作为接口的字段,而不是类本身

在尝试反序列化Json时,我无法找到解决错误的方法:

'无法创建类型为ConsoleApp1.IDisplayInstructions的实例。类型是接口或抽象类,无法实例化。路径'displayInstructions.AGB',第4行,位置34'

我理解它背后的含义;我需要指示Json反序列化器为接口成员使用哪个具体类。我只是不知道怎么做。我尝试使用JsonConstructor属性,或使用自定义反序列化程序,但两种方法都无法工作

还有一个类似的问题(),但这是一个作为接口的字段,而不是类本身

使用Newtonsoft.Json;
使用System.Collections.Generic;
名称空间控制台EAPP1
{
班级计划
{
静态void Main(字符串[]参数)
{
字符串jsonData=@”{
“术语”:“约翰”
,'resourceTypes':['POL','CLM','WRK']
,'displayInstructions':{'AGB':{'DisplayAttributes':['AssuredName','PolicyNumber','DistributorName','EffectiveDate'],'Format':'|资源类型|(|秩|){0}/{1}
,'AGT':{'DisplayAttributes':['AssuredName','PolicyNumber','DistributorName','EffectiveDate','Format':'|资源类型|(|秩|){0}/{1}
,'AGY':{'DisplayAttributes':['AssuredName','PolicyNumber','DistributorName','EffectiveDate','Format':'|资源类型|(|秩|){0}/{1}
,'CLM':{'DisplayAttributes':['AssuredName','PolicyNumber','DistributorName','EffectiveDate','Format':'|资源类型|(|秩|){0}/{1}
,'PLU':{'DisplayAttributes':['AssuredName','PolicyNumber','DistributorName','EffectiveDate','Format':'|资源类型|(|秩|){0}/{1}/{2}
,'POL':{'DisplayAttributes':['AssuredName','PolicyNumber','DistributorName','EffectiveDate','Format':'|资源类型|(|秩|){0}/{1}/{2}
,'PRV':{'DisplayAttributes':['AssuredName','PolicyNumber','DistributorName','EffectiveDate','Format':'|资源类型|(|秩|){0}/{1}}
}";
SearchCriteria sc=Newtonsoft.Json.JsonConvert.DeserializeObject(jsonData);
}
}
接口标准
{
字符串项{get;set;}
IEnumerable ResourceTypes{get;set;}
IDisplayInstructions显示指令{get;set;}
}
类搜索条件:ISearchCriteria
{
公共字符串项{get;set;}
公共IEnumerable ResourceTypes{get;set;}
公共IDisplayInstructions显示说明
{
获取{将this.displayInstructions作为IDisplayInstructions返回;}
设置
{
this.displayInstructions=新的displayInstructions();
foreach(var kvp值)
{
这个.displayInstructions.Add(kvp.Key,kvp.Value);
}
}
}
专用显示指令显示指令;
[JsonConstructor]
公共搜索条件(字符串术语、IEnumerable ResourceType、IDisplayInstructions和displayInstructions)
{
这个术语=术语;
this.ResourceTypes=ResourceTypes;
this.DisplayInstructions=DisplayInstructions;
}
}
接口IDisplayInstructions:IDictionary{}
类显示说明:字典{}
接口IDisplay指令
{
IEnumerable DisplayAttributes{get;set;}
字符串格式{get;set;}
}
类DisplayInstruction:IDisplayInstruction
{
公共IEnumerable显示属性{get;set;}
公共字符串格式{get;set;}
}
}

上面Matthew Groves()提供的帖子有一半答案,另一半以JsonDictionary属性()的形式出现。我能够保持接口方法,因为它确实适合我所追求的单元测试方法

最终代码:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            string jsonData = @"{
    'Term' : 'john'
   ,'resourceTypes' : ['POL', 'CLM', 'WRK']
   ,'displayInstructions': {'AGB' : {'displayAttributes' : ['AssuredName','PolicyNumber','DistributorName','EffectiveDate'] ,'format':'|resource_type| (|rank|) {0} / {1}'}
                           ,'POL' : {'displayAttributes' : ['AssuredName','PolicyNumber','DistributorName','EffectiveDate'] ,'format':'|resource_type| (|rank|) {0} / {1}'}}
}";

            SearchCriteria des = JsonConvert.DeserializeObject<SearchCriteria>(jsonData);
        }
    }

    interface ISearchCriteria
    {
        string Term { get; set; }
        IEnumerable<string> ResourceTypes { get; set; }
        IDisplayInstructions DisplayInstructions { get; set; }
    }

    public class ConfigConverter<I, T> : JsonConverter
    {
        public override bool CanWrite => false;
        public override bool CanRead => true;
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(I);
        }
        public override void WriteJson(JsonWriter writer,
            object value, JsonSerializer serializer)
        {
            throw new InvalidOperationException("Use default serialization.");
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var jsonObject = JObject.Load(reader);
            var deserialized = (T)Activator.CreateInstance(typeof(T));
            serializer.Populate(jsonObject.CreateReader(), deserialized);
            return deserialized;
        }
    }

    class SearchCriteria : ISearchCriteria
    {
        public string Term { get; set; }
        public IEnumerable<string> ResourceTypes { get; set; }

        [JsonConverter(typeof(ConfigConverter<IDisplayInstructions, DisplayInstructions>))]
        public IDisplayInstructions DisplayInstructions { get; set; }
    }

    interface IDisplayInstructions : IDictionary<string, IDisplayInstruction> { }

    [JsonDictionary(ItemConverterType = typeof(ConfigConverter<IDisplayInstruction, DisplayInstruction>))]
    class DisplayInstructions : Dictionary<string, IDisplayInstruction>, IDisplayInstructions
    {

    }

    interface IDisplayInstruction
    {
        IEnumerable<string> DisplayAttributes { get; set; }
        string Format { get; set; }
    }

    [JsonConverter(typeof(ConfigConverter<IDisplayInstruction, DisplayInstruction>))]
    class DisplayInstruction : IDisplayInstruction
    {
        public IEnumerable<string> DisplayAttributes { get; set; }
        public string Format { get; set; }
    }
}
使用Newtonsoft.Json;
使用Newtonsoft.Json.Linq;
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用System.Xml;
名称空间控制台EAPP1
{
班级计划
{
静态void Main(字符串[]参数)
{
字符串jsonData=@”{
“术语”:“约翰”
,'resourceTypes':['POL','CLM','WRK']
,'displayInstructions':{'AGB':{'displayAttributes':['AssuredName','PolicyNumber','DistributorName','EffectiveDate'],'format':'|资源类型|(|秩|){0}/{1}
,'POL':{'displayAttributes':['AssuredName','PolicyNumber','DistributorName','EffectiveDate','format':'|资源类型|(|秩|){0}/{1}}
}";
SearchCriteria des=JsonConvert.DeserializeObject(jsonData);
}
}
接口标准
{
字符串项{get;set;}
IEnumerable ResourceTypes{get;set;}
IDisplayInstructions显示指令{get;set;}
}
公共类ConfigConverter:JsonConverter
{
公共覆盖boolcanwrite=>false;
public override bool CanRead=>true;
公共覆盖布尔CanConvert(类型objectType)
{
return objectType==typeof(I);
}
public override void WriteJson(JsonWriter writer,
对象值,JsonSerializer序列化程序)
{
抛出新的InvalidOperationException(“使用默认序列化”);
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
var jsonObject=JObject.Load(读卡器);
var反序列化=(T)Activator.CreateInstance(typeof(T));
填充(jsonObject.CreateReader(),反序列化);
返回反序列化;
}
}
类搜索条件:ISearchCriteria
{
公共字符串项{get;set;}
公共IEnumerable ResourceTypes{get;set;}
[JsonConverter(类型(配置转换器))]