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

如何用YamlDotNet序列化动态JSON?嵌套列表序列化异常

使用YamlDotNet处理动态JSON转YAML的嵌套列表问题

我需要用YamlDotNet库将JSON转换为YAML文件,但输入JSON的结构无法预知,必须用动态对象处理。最初定义的plugins类如下:

public class plugins
{
     public string name { get; set; }
     public object config { get; set; }
}

用这个类序列化后结果异常,按照建议把config属性改为IDictionary<string, object>后,普通JSON能正常序列化,但遇到包含嵌套列表的JSON时,列表内容会被序列化为空数组。

示例JSON:

{
    "name": "correlation-id",
    "config": {
        "add": {
            "headers": [
                "content-encoding:deflate,gzip",
                "accept-encoding:deflate,gzip;q=1.0,*;q=0.5%"
            ]
        }
    }
}

对应的异常YAML结果:

plugins:
- name: correlation-id
  config:
    generator: uuid
    header_name: Aura-Correlation-Id
    echo_downstream: true
- name: correlation-id
  config:
    config: data
    header_name: Aura-Correlation-Id
    val3: true
- name: correlation-id
  config:
    add:
      headers:
      - []
      - []

试过直接传入JSON字符串或用JObject处理都无效,请问该如何修改类,或者是否需要编写自定义转换器?


解决方案

1. 改用JObject存储config属性

将plugins类的config类型改为JObject(来自Newtonsoft.Json库),JObject能完整保留JSON的嵌套结构,包括数组类型:

public class plugins
{
    public string name { get; set; }
    public JObject config { get; set; }
}

序列化时,YamlDotNet可以直接识别JObject的结构,无需额外处理,就能正确序列化嵌套列表。

2. 编写自定义YamlDotNet类型转换器

如果不想依赖JObject,可以自定义一个类型转换器,处理动态对象中的数组和嵌套结构:

public class DynamicObjectConverter : IYamlTypeConverter
{
    public bool Accepts(Type type)
    {
        return type == typeof(object) 
            || type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>))
            || type.IsArray 
            || type.GetInterface(nameof(IEnumerable)) != null;
    }

    public object ReadYaml(IParser parser, Type type)
    {
        // 若不需要反序列化YAML到对象,可直接抛出异常或返回null
        throw new NotImplementedException();
    }

    public void WriteYaml(IEmitter emitter, object value, Type type)
    {
        // 处理字典类型
        if (value is IDictionary<string, object> dict)
        {
            emitter.Emit(new MappingStart());
            foreach (var kvp in dict)
            {
                emitter.Emit(new Scalar(kvp.Key));
                WriteYaml(emitter, kvp.Value, kvp.Value?.GetType() ?? typeof(object));
            }
            emitter.Emit(new MappingEnd());
        }
        // 处理集合/数组类型(排除字符串)
        else if (value is IEnumerable enumerable && !(value is string))
        {
            emitter.Emit(new SequenceStart());
            foreach (var item in enumerable)
            {
                WriteYaml(emitter, item, item?.GetType() ?? typeof(object));
            }
            emitter.Emit(new SequenceEnd());
        }
        // 处理普通值类型
        else
        {
            emitter.Emit(new Scalar(value?.ToString()));
        }
    }
}

序列化时注册这个转换器即可:

var serializer = new SerializerBuilder()
    .WithTypeConverter(new DynamicObjectConverter())
    .Build();

string yamlContent = serializer.Serialize(yourPluginsList);

3. 直接处理动态JSON对象(推荐)

跳过自定义类,直接用Newtonsoft.Json将JSON字符串转为动态对象,再用YamlDotNet序列化,这种方式最适合结构不确定的场景:

// 先将JSON转为动态对象
dynamic dynamicJson = JsonConvert.DeserializeObject(yourJsonString);
// 序列化为YAML
var serializer = new SerializerBuilder().Build();
string yamlContent = serializer.Serialize(dynamicJson);

这种方式无需定义固定类,能自动识别JSON中的嵌套列表、对象等结构,序列化结果完全符合预期。


内容的提问来源于stack exchange,提问作者Abdulvahap ÖZTEL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:05:23