如何用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
相关产品推荐
相关产品推荐

