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

使用Newtonsoft JsonConvert序列化时将非对象值替换为类型名

解决方案

你可以通过两种方式实现需求:从.NET对象直接生成类型名结构的JSON,或者从现有JSON字符串转换得到目标结果。

场景1:从.NET对象生成类型名JSON

自定义一个JsonConverter,在序列化时将每个属性值替换为对应的类型名称,同时递归处理对象和数组结构:

using Newtonsoft.Json;
using System;
using System.Collections;
using System.Reflection;

public class TypeNameJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType) => true;

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value == null)
        {
            writer.WriteNull();
            return;
        }

        Type type = value.GetType();

        // 处理值类型与字符串
        if (type.IsValueType || type == typeof(string))
        {
            string typeName = type.Name;
            // 映射特殊类型名称
            if (type == typeof(Guid)) typeName = "Guid";
            else if (type == typeof(DateTimeOffset)) typeName = "DateTimeOffset";
            
            writer.WriteValue(typeName);
        }
        // 处理数组与集合
        else if (type.IsArray || typeof(IEnumerable).IsAssignableFrom(type) && type != typeof(string))
        {
            writer.WriteStartArray();
            foreach (var item in (IEnumerable)value)
            {
                WriteJson(writer, item, serializer);
            }
            writer.WriteEndArray();
        }
        // 处理嵌套对象
        else
        {
            writer.WriteStartObject();
            foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                var propValue = prop.GetValue(value);
                writer.WritePropertyName(prop.Name);
                WriteJson(writer, propValue, serializer);
            }
            writer.WriteEndObject();
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException("此转换器仅支持序列化操作");
    }
}

使用示例:

var data = new {
    organisationId = Guid.Empty,
    submittedAt = new DateTimeOffset(2023, 5, 8, 21, 58, 50, TimeSpan.Zero),
    multiple = new int[] { 123 },
    obj = new {
        innerEx1 = "hello world",
        innerEx2 = 123
    }
};

string resultJson = JsonConvert.SerializeObject(data, Formatting.Indented, new TypeNameJsonConverter());

场景2:从现有JSON字符串转换

先解析JSON为JToken,遍历所有节点并替换值为对应类型名称:

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

public static class JsonTypeMapper
{
    public static JToken ReplaceValuesWithTypeNames(JToken token)
    {
        switch (token.Type)
        {
            case JTokenType.Object:
                foreach (JProperty prop in token.Children<JProperty>())
                {
                    prop.Value = ReplaceValuesWithTypeNames(prop.Value);
                }
                return token;
            case JTokenType.Array:
                for (int i = 0; i < token.Count(); i++)
                {
                    token[i] = ReplaceValuesWithTypeNames(token[i]);
                }
                return token;
            case JTokenType.String:
                string strVal = token.Value<string>();
                if (Guid.TryParse(strVal, out _))
                    return JToken.FromObject("Guid");
                else if (DateTimeOffset.TryParse(strVal, out _))
                    return JToken.FromObject("DateTimeOffset");
                else
                    return JToken.FromObject("string");
            case JTokenType.Integer:
                return JToken.FromObject("int");
            case JTokenType.Float:
                return JToken.FromObject("double");
            case JTokenType.Boolean:
                return JToken.FromObject("bool");
            case JTokenType.Null:
                return JToken.FromObject("null");
            default:
                return JToken.FromObject(token.Type.ToString());
        }
    }
}

使用示例:

string inputJson = @"
{
    ""organisationId"": ""00000000-0000-0000-0000-000000000000"",
    ""submittedAt"": ""2023-05-08T21:58:50+00:00"",
    ""multiple"": [
        123
    ],
    ""obj"": {
        ""innerEx1"": ""hello world"",
        ""innerEx2"": 123
    }
}";

JToken inputToken = JToken.Parse(inputJson);
JToken outputToken = JsonTypeMapper.ReplaceValuesWithTypeNames(inputToken);
string resultJson = outputToken.ToString(Formatting.Indented);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:22:46