我需要一种方法通过 asp.net 6 后端读取 json 配置,并将其以 json 格式和驼峰属性名称发送到前端。原始 json 配置使用 PascalCasing 作为其属性名称。后端不知道 json 的格式,因此不可能进行类型化对象绑定。
我尝试的方法是让 ASP.NET 将 json 的这些部分绑定到对象或 JsonElement 属性,但这似乎不起作用,因为未使用默认使用驼峰命名法的 ASP.NET 标准序列化选项通过 JsonElement 序列化器。这看起来非常奇怪和意外的行为,但已被报告并确认为此处的设计功能: https://github.com/dotnet/runtime/issues/61843 https://github.com/dotnet/runtime/issues/66661
第一个指出您不能使用 JsonElement 来实现此目的,而应该使用 JsonNode。 第二个指出 JsonNode 也不支持这一点,这是设计上的。官方文档也证实了这一点。 那么我应该如何使用标准 System.Text.Json 工具提供此功能?对于这种情况,必须编写自己的转换器或使用 Newtonsoft 进行转换似乎很荒谬。
一篇中等帖子似乎提到可以通过在 JsonObject 上使用 ToJsonString 序列化器选项来实现这一点,但我无法复制这种行为。对于我来说,在 .net 6 和 .net 8 上,命名策略仍然被忽略,并且 ToJsonString 输出与从配置中读取的相同的 json。 https://medium.com/@serhiikokhan/mastering-the-use-of-system-text-json-e4d37564ab44
任何提示或建议将不胜感激。
正如您所指出的,此行为是由 MSFT 设计的,请参阅已解决的问题 JsonNode 不尊重 PropertyNamingPolicy #66661 进行确认。
JsonConverter<JsonNode>
,使用 JsonNode
指定的命名策略来编写
JsonSerializerOptions.PropertyNamingPolicy
层次结构,如下所示:
public class NamingPolicyJsonNodeConverter : JsonConverter<JsonNode>
{
public override bool CanConvert(Type typeToConvert) => typeof(JsonNode).IsAssignableFrom(typeToConvert) && !typeof(JsonValue).IsAssignableFrom(typeToConvert);
public override void Write(Utf8JsonWriter writer, JsonNode? value, JsonSerializerOptions options)
{
var namingPolicy = options.PropertyNamingPolicy;
switch (value)
{
case JsonObject obj:
writer.WriteStartObject();
foreach (var pair in obj)
{
writer.WritePropertyName(namingPolicy?.ConvertName(pair.Key) ?? pair.Key);
Write(writer, pair.Value, options);
}
writer.WriteEndObject();
break;
case JsonArray array: // We need to handle JsonArray explicitly to ensure that objects inside arrays are alphabetized
writer.WriteStartArray();
foreach (var item in array)
Write(writer, item, options);
writer.WriteEndArray();
break;
case null:
writer.WriteNullValue();
break;
default: // JsonValue
value.WriteTo(writer, options);
break;
}
}
public override JsonNode? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => JsonNode.Parse(ref reader);
}
然后在重新序列化
JsonNode
层次结构时使用它来重新映射属性名称,如下所示:
var options = new JsonSerializerOptions
{
Converters = { new NamingPolicyJsonNodeConverter() },
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true,
};
// Parse or deserialize the JSON using one of the two methods:
// var node = JsonSerializer.Deserialize<JsonNode>(inputJson, options);
var node = JsonNode.Parse(inputJson);
// Then serializing using the specified options + converter to remap property names:
var outputJson = JsonSerializer.Serialize(node, options);
演示 .NET 6 fiddle 这里。