【发布时间】:2021-12-28 00:05:37
【问题描述】:
我会以我试图避免使用 Newtonsoft.Json 的事实作为开头,因为从表面上看,System.Text.Json 已准备好在 .NET 6 中的黄金时间。
所以我有两个来自 API 的枚举,我想使用这种测试方法对它们进行反序列化:
[Theory]
[ClassData(typeof(TestDataGenerator))]
public void CanDeserialiseEnumsWithCustomJsonStrings(Enum expected, string jsonName)
{
jsonName.ShouldNotBeNullOrEmpty();
ReadOnlySpan<char> json = $"{{\"TestEnum\":\"{jsonName}\"}}";
Type constructed = typeof(TestEnumWrapper<>).MakeGenericType(expected.GetType());
var res = JsonSerializer.Deserialize(json, constructed);
constructed.GetProperty("TestEnum").GetValue(res).ShouldBe(expected);
}
private class TestEnumWrapper<T> where T: struct
{
public T TestEnum { get; set; }
}
(是的,我知道这可以通过JsonSerializer.Deserialize<T>() 完成,我希望能够通过此测试测试多种类型,因此我需要反射 AFAICT)。
第一个,工作正常:
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum RecordType
{
[JsonPropertyName("country")]
Country = 1,
[JsonPropertyName("destinationOrbit")]
DestinationOrbit = 2,
[JsonPropertyName("engine")]
Engine = 3,
//etc...
}
第二个,反序列化失败,这似乎是由于名称中的空格。
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum ObjectClass
{
[JsonPropertyName("Rocket Body")]
RocketBody,
[JsonPropertyName("Rocket Debris")]
RocketDebris,
[JsonPropertyName("Rocket Fragmentation Debris")]
RocketFragmentationDebris,
[JsonPropertyName("Rocket Mission Related Object")]
RocketMissionRelatedObject,
//etc...
}
API 由欧洲航天局控制,所以不知何故,我认为我无法说服他们进一步合理化响应。
有没有办法解决这个问题?
有些人要求提供我尝试反序列化的 JSON 示例。我目前正在处理这个 blob 的属性部分:
{
"type": "object",
"attributes": {
"shape": null,
"xSectMin": null,
"satno": null,
"depth": null,
"objectClass": "Rocket Fragmentation Debris",
"cosparId": null,
"length": null,
"height": null,
"mass": null,
"xSectMax": null,
"vimpelId": 84303,
"xSectAvg": null,
"name": null
},
"relationships": {
"states": {
"links": {
"self": "/api/objects/61345/relationships/states",
"related": "/api/objects/61345/states"
}
},
"initialOrbits": {
"links": {
"self": "/api/objects/61345/relationships/initial-orbits",
"related": "/api/objects/61345/initial-orbits"
}
},
"destinationOrbits": {
"links": {
"self": "/api/objects/61345/relationships/destination-orbits",
"related": "/api/objects/61345/destination-orbits"
}
},
"operators": {
"links": {
"self": "/api/objects/61345/relationships/operators",
"related": "/api/objects/61345/operators"
}
},
"launch": {
"links": {
"self": "/api/objects/61345/relationships/launch",
"related": "/api/objects/61345/launch"
}
},
"reentry": {
"links": {
"self": "/api/objects/61345/relationships/reentry",
"related": "/api/objects/61345/reentry"
}
}
},
"id": "61345",
"links": {
"self": "/api/objects/61345"
}
}
【问题讨论】:
-
System.Text.Json 不支持。请参阅:System.Text.Json: How do I specify a custom name for an enum value?,其中有一些建议的解决方法。
-
反序列化
RecordType有效,因为正如docs 中所述,读取不区分大小写。 可以使用@ 自定义写入987654331@。请注意,这意味着JsonNamingPolicy无法自定义阅读。 -
在
Newtonsoft.Json中工作正常。不要折磨自己。在System.Text.Json中是可能的,但需要大量自定义代码或 Nuget。 -
你能发布你拥有的真实json吗?很难理解是什么问题,为什么必须反序列化或序列化枚举?
-
@Serge - 已添加 :)
标签: c# json enums deserialization system.text.json