gpt4 book ai didi

c# - 使用 Json.NET PopulateObject 将稀疏数据合并到字典中

转载 作者:太空宇宙 更新时间:2023-11-03 12:00:52 26 4
gpt4 key购买 nike

我想加载 JSON 格式的稀疏数据以获得用默认值填充缺失数据的结果,但我的默认值包括可扩展集的预定义实例,而不仅仅是固定字段。

对于(任意)例子,

类型

class Link
{
public string Addr;
public short Port;
public Link() { Addr = "0.0.0.0"; Port = 80; }
public override string ToString() { return Addr + ":" + Port.ToString(); }
}

class Targets
{
public Link Fixed;
public Dictionary<string, Link> Variable;
public Targets()
{
Fixed = new Link() { Addr = "192.168.0.1" };
Variable = new Dictionary<string, Link>
{
["Common"] = new Link() { Addr = "192.168.0.2" }
};
}

public override string ToString()
{
var result = new System.Text.StringBuilder();

result.Append("Fixed").Append('=').Append(Fixed)
.Append(' ');

foreach (var link in Variable)
{
result.Append(link.Key).Append('=').Append(link.Value)
.Append(' ');
}

return result.ToString();
}
}

用法

var targets = new Targets();

string json = @"{
'Fixed': { 'Port':12345 },
'Variable': {
'Common': { 'Port':12345 }
}
}";

Newtonsoft.Json.JsonConvert.PopulateObject(json, targets);

Console.WriteLine(targets);

输出 Fixed=192.168.0.1:12345 Common=0.0.0.0:12345 而不是所需的 Fixed=192.168.0.1:12345 Common=192.168.0.2:12345 .

这表明所需的合并逻辑适用于固定属性,但不适用于 Dictionary 中的项目,尽管事实上 Dictionary 将以其他方式序列化/反序列化,就像具有固定属性的类型一样。

最佳答案

我花了一段时间才弄明白这一点。 Json.NET has a dedicated function for merging two JObjects together .这是修改为使用此方法的示例:

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;

namespace ConsoleApp3
{
class Link
{
public string Addr;
public short Port;
public Link() { Addr = "0.0.0.0"; Port = 80; }
public override string ToString() { return Addr + ":" + Port.ToString(); }
}

class Targets
{
public Link Fixed;

public Dictionary<string, Link> Variable;

public Targets()
{
Fixed = new Link() { Addr = "192.168.0.1" };
Variable = new Dictionary<string, Link>
{
["Common"] = new Link() { Addr = "192.168.0.2" },
["Common2"] = new Link() { Addr = "192.168.0.25" }
};
}

public override string ToString()
{
var result = new System.Text.StringBuilder();

result.Append("Fixed").Append('=').Append(Fixed)
.Append(' ');

foreach (var link in Variable)
{
if (link.Key != "Variable")
result.Append(link.Key).Append('=').Append(link.Value)
.Append(' ');
}

return result.ToString();
}
}

class Program
{
static void Main(string[] args)
{
var targets = new Targets();

JObject o1 = JObject.Parse( @"{
'Fixed': { 'Port':12345 },
'Variable': {
'Common': { 'Port':12345 }
}
}");
JObject o2 = JObject.FromObject(targets);
o2.Merge(o1, new JsonMergeSettings
{
// union array values together to avoid duplicates
MergeArrayHandling = MergeArrayHandling.Union
});

string json = o2.ToString();

Console.WriteLine(json);
JsonConvert.PopulateObject(json, targets);

Console.WriteLine(targets);

Console.ReadKey();
}
}
}

输出是:

{
"Fixed": {
"Addr": "192.168.0.1",
"Port": 12345
},
"Variable": {
"Common": {
"Addr": "192.168.0.2",
"Port": 12345
},
"Common2": {
"Addr": "192.168.0.25",
"Port": 80
}
}
}
Fixed=192.168.0.1:12345 Common=192.168.0.2:12345 Common2=192.168.0.25:80

由 OP 编辑​​:改进为扩展方法,无需额外的 ToString/反序列化:

    static class SerializerExtensions
{
public static T MergeObject<T>(this JsonSerializer serializer, JsonReader json, T target)
{
JObject o1 = JObject.FromObject(target, serializer);
JObject o2 = serializer.Deserialize(json) as JObject;
o1.Merge(o2, new JsonMergeSettings
{ // union array values together to avoid duplicates
MergeArrayHandling = MergeArrayHandling.Union,
// an explicit null removes an existing item
MergeNullValueHandling = MergeNullValueHandling.Merge,
});

serializer.Populate(o1.CreateReader(), target);
return target;
}

public static T MergeObject<T>(this JsonSerializer serializer, JsonReader json, JObject template)
{
JObject o1 = template.DeepClone() as JObject;
JObject o2 = serializer.Deserialize(json) as JObject;
o1.Merge(o2, new JsonMergeSettings
{ // union array values together to avoid duplicates
MergeArrayHandling = MergeArrayHandling.Union,
// an explicit null removes an existing item
MergeNullValueHandling = MergeNullValueHandling.Merge,
});

return serializer.Deserialize<T>(o1.CreateReader());
}
}

关于c# - 使用 Json.NET PopulateObject 将稀疏数据合并到字典中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57085267/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com