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

使用Newtonsoft Json.NET序列化对象结构不符合第三方接口预期

问题:满足第三方接口的XML和JSON序列化要求(含重复属性的JSON格式)

需求说明

需要将数据序列化为符合第三方接口要求的XML和JSON格式,预期结果如下:

预期XML格式

<?xml version="1.0" encoding="utf-8"?>
<FooList>
    <Foo>
        <Name>George</Name>
        <Color>Blue</Color>
    </Foo>
    <Foo>
        <Name>Betty</Name>
        <Color>Green</Color>
    </Foo>
</FooList>

预期JSON格式

[
  {
    "Foo": {
      "Name": "George",
      "Color": "Blue"
    },
    "Foo": {
      "Name": "Betty",
      "Color": "Green"
    }
  }
]

注:第三方接口要求JSON包含重复的"Foo"属性名,尽管这不符合常规JSON规范,但必须满足该要求。

当前实现的数据模型

已创建以下C#类用于序列化:

[Serializable, XmlType(AnonymousType = true), XmlRoot(Namespace = "", ElementName = "FooList", IsNullable = false)]
public class FooListResponse
{
    [XmlElement("Foo", IsNullable = false)]
    public List<Foo> FooList { get; set; }
}

[Serializable]
public class Foo
{
    [XmlElement("Name"), JsonProperty("Name")]
    public string Name { get; set; }

    [XmlElement("Color"), JsonProperty("Color")]
    public string Color { get; set; }
}

当前序列化问题

  • XML序列化结果符合预期;
  • 使用Newtonsoft Json.NET的JsonConvert.SerializeObject序列化时,结果不符合要求:
    {
        "FooList": [
            {
                "Name": "George",
                "Color": "Blue"
            },
            {
                "Name": "Betty",
                "Color": "Green"
            }
        ]
    }
    
  • 尝试仅序列化FooList属性,结果仍不符合要求:
    [
        {
            "Name": "George",
            "Color": "Blue"
        },
        {
            "Name": "Betty",
            "Color": "Green"
        }
    ]
    
    缺少外层大括号及每个对象前的"Foo:"标识,且无法生成重复的"Foo"属性。需要无需重复定义数据模型的解决方案,因为实际模型远比示例复杂。

解决方案:自定义JsonConverter

通过为FooListResponse类编写自定义Json转换器,实现符合要求的JSON序列化,无需修改现有模型:

1. 实现自定义转换器

public class FooListResponseJsonConverter : JsonConverter<FooListResponse>
{
    public override void WriteJson(JsonWriter writer, FooListResponse value, JsonSerializer serializer)
    {
        // 写入外层数组
        writer.WriteStartArray();
        // 写入数组内的对象
        writer.WriteStartObject();
        
        // 为每个Foo对象写入重复的"Foo"属性
        foreach (var foo in value.FooList)
        {
            writer.WritePropertyName("Foo");
            serializer.Serialize(writer, foo);
        }
        
        writer.WriteEndObject();
        writer.WriteEndArray();
    }

    public override FooListResponse ReadJson(JsonReader reader, Type objectType, FooListResponse existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        // 实现反序列化逻辑(按需使用)
        var response = new FooListResponse { FooList = new List<Foo>() };
        if (reader.TokenType == JsonToken.StartArray)
        {
            reader.Read(); // 进入数组内的对象
            if (reader.TokenType == JsonToken.StartObject)
            {
                while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
                {
                    if ((string)reader.Value == "Foo")
                    {
                        var foo = serializer.Deserialize<Foo>(reader);
                        response.FooList.Add(foo);
                    }
                    else
                    {
                        reader.Skip(); // 跳过非Foo属性
                    }
                }
            }
        }
        return response;
    }
}

2. 使用转换器进行序列化

// 构造测试数据
var fooListResponse = new FooListResponse
{
    FooList = new List<Foo>
    {
        new Foo { Name = "George", Color = "Blue" },
        new Foo { Name = "Betty", Color = "Green" }
    }
};

// 配置序列化设置,添加自定义转换器
var jsonSettings = new JsonSerializerSettings();
jsonSettings.Converters.Add(new FooListResponseJsonConverter());

// 序列化生成符合要求的JSON
string json = JsonConvert.SerializeObject(fooListResponse, jsonSettings);

最终生成的JSON

运行上述代码后,将得到完全符合第三方要求的JSON格式:

[
  {
    "Foo": {
      "Name": "George",
      "Color": "Blue"
    },
    "Foo": {
      "Name": "Betty",
      "Color": "Green"
    }
  }
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 05:07:03