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

如何用Newtonsoft.Json自定义序列化生成指定JSON结构

实现自定义C#类到指定JSON格式的序列化

针对你的需求,我们可以通过自定义JSON转换器来实现FaactRecordDifferences类到目标JSON格式的序列化,下面分别介绍两种主流JSON库的实现方案:


方案一:使用Newtonsoft.Json(Json.NET)

Newtonsoft.Json的自定义转换器API灵活易用,适合快速实现复杂序列化逻辑。

1. 编写自定义转换器

创建针对List<FieldDifference>的转换器,将列表转换为JSON键值对,并根据type字段处理值的类型:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;

public class FieldDifferenceListConverter : JsonConverter<List<FieldDifference>>
{
    public override void WriteJson(JsonWriter writer, List<FieldDifference> value, JsonSerializer serializer)
    {
        writer.WriteStartObject();
        foreach (var field in value)
        {
            writer.WritePropertyName(field.FieldName);
            
            // 根据类型决定序列化方式
            if (field.type == typeof(string))
            {
                writer.WriteValue(field.FieldValue);
            }
            else
            {
                // 将字符串值转换为目标类型后序列化
                var convertedValue = Convert.ChangeType(field.FieldValue, field.type);
                writer.WriteValue(convertedValue);
            }
        }
        writer.WriteEndObject();
    }

    public override List<FieldDifference> ReadJson(JsonReader reader, Type objectType, List<FieldDifference> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        // 若需反序列化可在此实现,示例暂不提供
        throw new NotImplementedException("反序列化逻辑未实现");
    }
}

2. 标记需要转换的属性

在FaactRecordDifferences类的Fields属性上添加转换器标记:

public class FaactRecordDifferences
{
    public string Id { get; set; }
    public int Year { get; set; }

    [JsonConverter(typeof(FieldDifferenceListConverter))]
    public List<FieldDifference> Fields { get; set; }
}

public class FieldDifference
{
    public string FieldName { get; set; }
    public string FieldValue { get; set; }
    public Type type { get; set; }
}

3. 序列化示例

var record = new FaactRecordDifferences
{
    Id = "U123321",
    Year = 2024,
    Fields = new List<FieldDifference>
    {
        new() { FieldName = "SomeFirstField", FieldValue = "1200.21", type = typeof(double) },
        new() { FieldName = "AnotherTestField", FieldValue = "SomeStringValue", type = typeof(string) },
        new() { FieldName = "SomethingHere", FieldValue = "6120.40", type = typeof(double) }
    }
};

var json = JsonConvert.SerializeObject(record, Formatting.Indented);
Console.WriteLine(json);

方案二:使用System.Text.Json(.NET Core/.NET 5+ 默认库)

如果使用.NET官方的System.Text.Json,同样可以通过自定义转换器实现需求:

1. 编写自定义转换器

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

public class FieldDifferenceListConverter : JsonConverter<List<FieldDifference>>
{
    public override List<FieldDifference> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // 若需反序列化可在此实现,示例暂不提供
        throw new NotImplementedException("反序列化逻辑未实现");
    }

    public override void Write(Utf8JsonWriter writer, List<FieldDifference> value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        foreach (var field in value)
        {
            writer.WritePropertyName(field.FieldName);
            
            if (field.type == typeof(string))
            {
                writer.WriteStringValue(field.FieldValue);
            }
            else
            {
                // 转换类型后序列化
                var convertedValue = Convert.ChangeType(field.FieldValue, field.type);
                JsonSerializer.Serialize(writer, convertedValue, field.type, options);
            }
        }
        writer.WriteEndObject();
    }
}

2. 应用转换器

可以通过属性标记或序列化选项两种方式应用转换器:

  • 属性标记方式:和Newtonsoft.Json一样,在Fields属性上添加[JsonConverter(typeof(FieldDifferenceListConverter))]
  • 序列化选项方式:
var options = new JsonSerializerOptions
{
    Converters = { new FieldDifferenceListConverter() },
    WriteIndented = true // 格式化输出
};

var json = JsonSerializer.Serialize(record, options);
Console.WriteLine(json);

注意事项

  • FieldValue的字符串必须能正确转换为指定的type,否则会抛出转换异常,建议添加try-catch或提前验证值的格式。
  • 若需要支持特殊类型(如DateTime、Guid),可以在转换器中单独处理这些类型的转换逻辑。
  • 如果需要反序列化功能,需补充实现转换器中的Read方法,将JSON键值对转换回List<FieldDifference>。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:05:40