You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将嵌套结构的Customer对象序列化为Dictionary<string, string>

如何将嵌套类对象转换为带点分隔键的字典?

类结构

public class Customer
{
    public string ID { get; set; }
    public Address contact { get; set; }
}

public class Address
{
    public string city { get; set; }
}

预期输出

Dictionary<string, string> result = new Dictionary<string, string>()
{
    { "ID",  "1" },
    { "contact.city", "Miami" }
};

报错信息

Unhandled exception. Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: {. Path 'contact', line 1, position 21.
at Newtonsoft.Json.JsonTextReader.ReadStringValue(ReadType readType)

原代码

Customer customer = new Customer() { ID = "1",  contact = new Address() { city = "Miami" } };
string customerString = Newtonsoft.Json.JsonConvert.SerializeObject(customer);
Dictionary<string, string> result = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(customerString);

解决方案

直接反序列化失败的原因是:contact对应的值是嵌套JSON对象,而非字符串,无法直接映射到Dictionary<string, string>类型。可以通过递归遍历JSON结构、扁平化嵌套路径来实现需求,以下是两种可行方案:

方案一:递归扁平化JObject

直接利用JObject遍历所有属性,递归拼接嵌套路径作为字典键:

using Newtonsoft.Json.Linq;

Customer customer = new Customer() { ID = "1", contact = new Address() { city = "Miami" } };
JObject jObject = JObject.FromObject(customer);
Dictionary<string, string> result = new Dictionary<string, string>();

FlattenJObject(jObject, "", result);

// 递归处理嵌套结构的方法
void FlattenJObject(JToken token, string prefix, Dictionary<string, string> dict)
{
    if (token is JValue value)
    {
        dict.Add(prefix.Trim('.'), value.ToString());
        return;
    }

    if (token is JObject obj)
    {
        foreach (var prop in obj.Properties())
        {
            string newPrefix = string.IsNullOrEmpty(prefix) ? prop.Name : $"{prefix}.{prop.Name}";
            FlattenJObject(prop.Value, newPrefix, dict);
        }
    }
}

方案二:自定义JsonConverter

如果需要复用该逻辑,可以编写自定义转换器,统一处理扁平化逻辑:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class FlatDictionaryConverter : JsonConverter<Dictionary<string, string>>
{
    public override Dictionary<string, string> ReadJson(JsonReader reader, Type objectType, Dictionary<string, string> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jObject = JObject.Load(reader);
        var dict = new Dictionary<string, string>();
        FlattenJObject(jObject, "", dict);
        return dict;
    }

    public override void WriteJson(JsonWriter writer, Dictionary<string, string> value, JsonSerializer serializer)
    {
        // 若需将扁平化字典序列化回嵌套结构,可在此实现逻辑
        throw new NotImplementedException();
    }

    private void FlattenJObject(JToken token, string prefix, Dictionary<string, string> dict)
    {
        if (token is JValue value)
        {
            dict.Add(prefix.Trim('.'), value.ToString());
            return;
        }

        if (token is JObject obj)
        {
            foreach (var prop in obj.Properties())
            {
                string newPrefix = string.IsNullOrEmpty(prefix) ? prop.Name : $"{prefix}.{prop.Name}";
                FlattenJObject(prop.Value, newPrefix, dict);
            }
        }
    }
}

// 使用方式
Customer customer = new Customer() { ID = "1", contact = new Address() { city = "Miami" } };
string customerString = JsonConvert.SerializeObject(customer);
var result = JsonConvert.DeserializeObject<Dictionary<string, string>>(customerString, new FlatDictionaryConverter());

两种方案都能生成你预期的带点分隔键的字典结构,核心逻辑是递归解析嵌套JSON对象,将层级路径拼接为字典键,对应值提取为字符串。

内容的提问来源于stack exchange,提问作者Impostor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 17:20:10