C# 使用json.net动态反序列化对多种类型的json响应

C# 使用json.net动态反序列化对多种类型的json响应,c#,json.net,C#,Json.net,我有一个简单的API,可以为不同的任务生成不同类型的配置,因此我希望找到一种使用if/else动态解析响应的方法。但是由于某些原因,配置没有反序列化,因为它已经是一个字符串,并且Serialize()再次执行该操作 因此,JsonConvert.DeserializeObject(jsonString)就不起作用了 这是我的密码: void Main() { var json = new ApiResponse {name = "name1", type = "a", config =

我有一个简单的API,可以为不同的任务生成不同类型的配置,因此我希望找到一种使用if/else动态解析响应的方法。但是由于某些原因,配置没有反序列化,因为它已经是一个字符串,并且
Serialize()
再次执行该操作

因此,
JsonConvert.DeserializeObject(jsonString)
就不起作用了

这是我的密码:

void Main()
{
    var json = new ApiResponse {name = "name1", type = "a", config = "{'title' : 'hello world!', 'id' : 1}"};
    var jsonString = JsonConvert.SerializeObject(json);
    Console.WriteLine(jsonString);

    if (json.type == "a")
    {
        var handler = JsonConvert.DeserializeObject<typeAhandler>(jsonString);
        handler.Dump();
    }
    else if(json.type == "b")
    {
        var handler = JsonConvert.DeserializeObject<typeBhandler>(jsonString);
        handler.Dump();
    }
}

public class ApiResponse
{
    public string name { get; set; }
    public string type {get; set;}
    public string config {get;set;} 
}

// Type A Handler
public class typeAhandler
{
    public string name { get; set; }
    public typeAconfig config { get; set; }
}

public class typeAconfig
{
    public string title { get; set; }
    public int id { get; set; }
}

// Type B Handler
public class typeBhandler
{
    public string name { get; set; }
    public typeBconfig config { get; set; }
}

public class typeBconfig
{
    public string[] items { get; set; }
}
void Main()
{
var json=new-ApiResponse{name=“name1”,type=“a”,config=“{'title':'hello world!','id':1}”;
var jsonString=JsonConvert.SerializeObject(json);
Console.WriteLine(jsonString);
如果(json.type==“a”)
{
var handler=JsonConvert.DeserializeObject(jsonString);
handler.Dump();
}
else if(json.type==“b”)
{
var handler=JsonConvert.DeserializeObject(jsonString);
handler.Dump();
}
}
公开课回应
{
公共字符串名称{get;set;}
公共字符串类型{get;set;}
公共字符串配置{get;set;}
}
//键入一个处理程序
公共类TypeHandler
{
公共字符串名称{get;set;}
公共类型配置{get;set;}
}
公共类类型图
{
公共字符串标题{get;set;}
公共int id{get;set;}
}
//B型处理器
公共类typeBhandler
{
公共字符串名称{get;set;}
公共类型配置配置{get;set;}
}
公共类类型配置
{
公共字符串[]项{get;set;}
}

在3天内,我发布了4次不同问题的相同答案:-)

使用特定的JsonConvert类:

类程序
{
静态void Main(字符串[]参数)
{
var json=new-ApiResponse{Name=“name1”,Type=“a”,Config=“{'title':'hello world!','id':1}”;
//var json=new-ApiResponse{Name=“name1”,Type=“b”,Config=“{'items':['item1','item2']}”;
字符串apiResult=JsonConvert.SerializeObject(json);
var deserialized=JsonConvert.DeserializeObject

这是当
类型:b


考虑按以下方式进行-

   public static object DeserializeHandler(string jsonString, IDictionary<string, Type> handlers)
    {
        var jsonObject = JsonConvert.DeserializeObject<JToken>(jsonString);
        var type = jsonObject["type"].ToString();
        var handlerType = handlers[type];
        var config = jsonObject["config"].ToString();
        var handler = JsonConvert.DeserializeObject(config, handlerType);
        return handler;
    }
维护处理程序字典,以避免if…else

 public static void Main(string[] args)
 {
        var json = new ApiResponse { name = "name1", type = "a", config = "{'title' : 'hello world!', 'id' : 1}" };
        var jsonString = JsonConvert.SerializeObject(json);
        Console.WriteLine(jsonString);
        IDictionary<string, Type> handlers = new Dictionary<string, Type>
        {
            { "a", typeof(typeAconfig) },
            { "b", typeof(typeBconfig) }
        };
        var handler = DeserializeHandler(jsonString, handlers);
 }
publicstaticvoidmain(字符串[]args)
{
var json=new-ApiResponse{name=“name1”,type=“a”,config=“{'title':'hello world!','id':1}”;
var jsonString=JsonConvert.SerializeObject(json);
Console.WriteLine(jsonString);
IDictionary handlers=新字典
{
{“a”,typeof(typeAconfig)},
{“b”,typeof(typeBconfig)}
};
var handler=反序列化处理程序(jsonString,handlers);
}
函数反序列化处理程序如下所示-

   public static object DeserializeHandler(string jsonString, IDictionary<string, Type> handlers)
    {
        var jsonObject = JsonConvert.DeserializeObject<JToken>(jsonString);
        var type = jsonObject["type"].ToString();
        var handlerType = handlers[type];
        var config = jsonObject["config"].ToString();
        var handler = JsonConvert.DeserializeObject(config, handlerType);
        return handler;
    }
公共静态对象反序列化处理程序(字符串jsonString,IDictionary处理程序)
{
var jsonObject=JsonConvert.DeserializeObject(jsonString);
var type=jsonObject[“type”].ToString();
var handlerType=handlers[type];
var config=jsonObject[“config”].ToString();
var handler=JsonConvert.DeserializeObject(配置,handlerType);
返回处理程序;
}

我会这样做:

static void Main()
{
var json=new-ApiResponse{name=“name1”,type=“a”,config=“{'title':'hello world!','id':1}”;
var jsonString=JsonConvert.SerializeObject(json);
Console.WriteLine(jsonString);
如果(json.type==“a”)
{
var handler=JsonConvert.DeserializeObject(jsonString);
//handler.Dump();
}
else if(json.type==“b”)
{
var handler=JsonConvert.DeserializeObject(jsonString);
//handler.Dump();
}
}
公开课回应
{
公共字符串名称{get;set;}
公共字符串类型{get;set;}
公共字符串配置{get;set;}
}
//键入一个处理程序
公共类TypeHandler
{
[JsonProperty(“名称”)]
公共字符串名称{get;set;}
[JsonIgnore]公共类型配置{get;set;}
[JsonProperty(“配置”)]
公共动态配置
{
set=>config=JsonConvert.DeserializeObject(值);
}
}
公共类类型图
{
公共字符串标题{get;set;}
公共int id{get;set;}
}
//B型处理器
公共类typeBhandler
{
[JsonProperty(“名称”)]
公共字符串名称{get;set;}
[JsonIgnore]
公共类型配置配置{get;set;}
[JsonProperty(“配置”)]
公共动态配置
{
set=>config=JsonConvert.DeserializeObject(值);
}
}
公共类类型配置
{
公共字符串[]项{get;set;}
}

关键是将配置类型以动态方式公开给JSONCOMVERT,然后在后台将其转换为您想要的类型并在应用程序中使用它

我不完全清楚您想要什么,但您可以使用自定义属性执行类似操作,以避免使用if/else和反射来进行对象构造

internal class Program
{
    public static void Main(string[] args)
    {
        var json = new ApiResponse { Name = "name1", Type = "a", Config = "{'title' : 'hello world!', 'id' : 1}" };
        var jsonString = JsonConvert.SerializeObject(json);
        ParseAndDumpConfig(jsonString);

        json = new ApiResponse { Name = "name2", Type = "b", Config = "{'Items' : ['Item-1', 'Item-2', 'Item-3']}" };
        jsonString = JsonConvert.SerializeObject(json);
        ParseAndDumpConfig(jsonString);
    }

    private static void ParseAndDumpConfig(string jsonString)
    {
        Console.WriteLine();
        Console.WriteLine("Parsing Api Response:");
        Console.WriteLine(jsonString);

        var json = JsonConvert.DeserializeObject<ApiResponse>(jsonString);

        if (_typeMap.TryGetValue(json.Type, out var t))
        {
            var config = JsonConvert.DeserializeObject(json.Config, t);

            Type genericType = typeof(TypeHandler<>).MakeGenericType(t);

            var constructedObject = Activator.CreateInstance(genericType, new object[] { json.Name, config });

            var result = Convert.ChangeType(constructedObject, genericType);

            Console.WriteLine($"Parsed to [{result.GetType().FullName}]:");
            Console.WriteLine(result);
        }
        else
        {
            Console.WriteLine($"Config map for \"{json.Type}\" not found.");
        }
    }

    private static readonly Dictionary<string, Type> _typeMap = Assembly.GetExecutingAssembly().GetTypes()
        .Where(x => x.CustomAttributes.Any(y => y.AttributeType == typeof(DeserializeTypeMapAttribute)))
        .ToDictionary(x => x.GetCustomAttribute<DeserializeTypeMapAttribute>().Name);
}

public class ApiResponse
{
    public string Name { get; set; }
    public string Type { get; set; }
    public string Config { get; set; }
}

public class TypeHandler<TConfig>
{
    public string Name { get; set; }
    public TConfig Config { get; set; }

    public TypeHandler(string name, TConfig config)
    {
        Name = name;
        Config = config;
    }

    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);
    }
}

[DeserializeTypeMap("a")]
public class TypeAconfig
{
    public string Title { get; set; }
    public int Id { get; set; }

    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);
    }
}

[DeserializeTypeMap("b")]
public class TypeBconfig
{
    public string[] Items { get; set; }

    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);
    }
}

[AttributeUsage(AttributeTargets.Class)]
public class DeserializeTypeMapAttribute : Attribute
{
    public string Name { get; }

    public DeserializeTypeMapAttribute(string name)
    {
        Name = name;
    }
}
内部类程序
{
公共静态void Main(字符串[]args)
{
var json=new-ApiResponse{Name=“name1”,Type=“a”,Config=“{'title':'hello world!','id':1}”;
var jsonString=JsonConvert.SerializeObject(json);
ParseAndDumpConfig(jsonString);
json=新的ApiResponse{Name=“name2”,Type=“b”,Config=“{'Items':['Item-1','Item-2','Item-3']}”;
jsonString=JsonConvert.SerializeObject(json);
ParseAndDumpConfig(jsonString);
}
私有静态void ParseAndDumpConfig(字符串jsonString)
{
Console.WriteLine();
WriteLine(“解析Api响应:”);
Console.WriteLine(jsonString);
var json=JsonConvert.DeserializeObject(jsonString);
if(_typeMap.TryGetValue(json.Type,out var t))
{
var config=JsonConvert.DeserializeObject(json.config,t);
Type genericType=typeof(TypeHandler)。MakeGenericType(t);
var constructedObject=Activato