【问题标题】:How to apply JsonExtensionData (Dictionary<string, JToken>) to another object with JSON.Net如何使用 JSON.Net 将 JsonExtensionData (Dictionary<string, JToken>) 应用于另一个对象
【发布时间】:2018-10-13 11:00:35
【问题描述】:

我遇到了这种(看似常见的)场景,但找不到令人满意的解决方案。也许有人知道:

出于某种原因,我解析 JSON 并允许用户提供比我的类具有的属性更多的键值对。我像这样存储任意的:

class MusterNode
{
    // some definite property
    public string TypeName { get; set; }

    // takes the rest
    // see https://www.newtonsoft.com/json/help/html/DeserializeExtensionData.htm
    [JsonExtensionData]
    private Dictionary<string, JToken> _extparams;
}

如果我反序列化类似的东西

{
   "TypeName": "a",
   "stuff": 3
}

TypeName 将被设置并且我的 _extparams 包含一个键“stuff”。

出于某种原因,我想将存储的数据应用到另一个(刚刚创建的)对象“obj”(实际上,参数被认为是那个类型名的东西)。 所以我有一个字典和一个对象。有没有办法在不先序列化的情况下“应用”字典?

我不满意的解决方案是:

string json = JsonConvert.SerializeObject(_extparams);
JsonConvert.PopulateObject(json, obj);

用一些 JsonSerializerSettings 装饰,这对我有用。但它做了不必要的工作。

【问题讨论】:

  • 你的obj是什么类型的?
  • 对于这个问题并不重要。想象一下序列化的键值对匹配对象的属性和类型(通过智能)

标签: c# .net json serialization json.net


【解决方案1】:

Json.Net 没有直接从标准字典中填充对象的方法。毕竟是序列化库,不是映射库。也就是说,有一种方法可以让它在没有中间序列化/反序列化步骤的情况下工作。

首先,不要使用Dictionary&lt;string, JToken&gt; 作为[JsonExtensionData] 参数的容器,而是使用JObjectJObject 实现了IDictionary&lt;string, JToken&gt;,所以它仍然可以捕获额外的属性。

class MusterNode
{
    ...
    [JsonExtensionData]
    private JObject _extparams;
}

然后,要填充另一个对象,您只需从JObject 创建一个读取器并将其传递给JsonSerializer.Populate(),如下所示:

new JsonSerializer().Populate(_extparams.CreateReader(), obj);

如果您有特定的序列化设置需要,您可以在调用Populate()之前直接在JsonSerializer上进行设置。

这是一个工作演示:https://dotnetfiddle.net/kIzc5G

【讨论】:

  • 工作起来很方便。谢谢。 SerializationSettings 可以这样设置:new JsonSerializer() { Converters = { new RGBPixelConverter() }, MissingMemberHandling = MissingMemberHandling.Error, }.Populate(_extparams.CreateReader(), obj);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-29
  • 1970-01-01
  • 2019-12-21
相关资源
最近更新 更多