将名称/值对反序列化为对象

Chr*_*ler 4 c# json json.net

我有一个名称/值对的集合,它们用单词名称和值来定义,就像键/值对象一样,即

[{"Name":"ActivityId","DataType":1,"Value":"a7868f8c-07ac-488d-a414-714527c2e76f"}, 
 {"Name":"Address1","DataType":2,"Value":"123 Main St"}]
Run Code Online (Sandbox Code Playgroud)

如果我有一个像这样的对象:

class Request
{
    public Guid ActivityId { get; set; }
    public string Address1 {get; set; }
}
Run Code Online (Sandbox Code Playgroud)

如何将其反序列化为上面的类?

我应该考虑使用自定义转换器吗?Json.NET 有内置的东西吗?有没有办法用我缺少的属性来装饰属性?自定义序列化会更容易吗?

我试图避免从字典中提取每个属性的数据,这将是一种简单的方法,但需要我对每个自定义实现都这样做。我更喜欢使用 Json.NET(或 .NET 框架中的某些内容)在单一方法中的基类中执行此操作。

我已经搜索了很多,大多数示例都是真实的名称/值对,没有以名称和值作为前缀,即

[{"ActivityId":"a7868f8c-07ac-488d-a414-714527c2e76f"}]
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Bri*_*ers 5

这可以通过JsonConverter像下面这样的自定义以简单的方式完成。转换器的工作方式是首先将名称-值对数组转换为JObject具有镜像对的属性,然后JObject使用序列化程序的内置Populate方法从 填充目标对象。

class NameValueConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // Load the array of name-value pairs and transform into a JObject.
        // We are assuming all the names will be distinct.
        JObject obj = new JObject(
            JArray.Load(reader)
                  .Children<JObject>()
                  .Select(jo => new JProperty((string)jo["Name"], jo["Value"]))
        );

        // Instantiate the target object and populate it from the JObject.
        object result = Activator.CreateInstance(objectType);
        serializer.Populate(obj.CreateReader(), result);
        return result;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // WriteJson is not called when CanWrite returns false
        throw new NotImplementedException();
    }

    public override bool CanConvert(Type objectType)
    {
        // We only want this converter to handle classes that are expressly
        // marked with a [JsonConverter] attribute, so return false here.
        // (CanConvert is not called when [JsonConverter] attribute is used.)
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

要使用转换器,只需[JsonConverter]向目标类添加一个属性:

[JsonConverter(typeof(NameValueConverter))]   
class Request
{
    public Guid ActivityId { get; set; }
    public string Address1 {get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以像往常一样反序列化:

Request req = JsonConvert.DeserializeObject<Request>(json);
Run Code Online (Sandbox Code Playgroud)

小提琴:https : //dotnetfiddle.net/tAp1Py