我將首先說明我試圖避免使用這一事實,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"
}
}
uj5u.com熱心網友回復:
這是一個解決方案 System.Text.Json
我使用了 Nuget 包System.Text.Json.EnumExtensions
https://github.com/StefH/System.Text.Json.EnumExtensions
// you probably want these options somewhere global
private JsonSerializerOptions options;
private class TestEnumWrapper<T> where T : struct
{
public T TestEnum { get; set; }
}
public enum ObjectClass
{
[EnumMember(Value = "Rocket Body")]
RocketBody,
[EnumMember(Value = "Rocket Debris")]
RocketDebris,
[EnumMember(Value = "Rocket Fragmentation Debris")]
RocketFragmentationDebris,
[EnumMember(Value = "Rocket Mission Related Object")]
RocketMissionRelatedObject,
//etc...
}
private void CanDeserialiseEnumsWithCustomJsonStrings(Enum expected, string jsonName)
{
var json = $"{{\"TestEnum\":\"{jsonName}\"}}";
Type constructed = typeof(TestEnumWrapper<>).MakeGenericType(expected.GetType());
var res = JsonSerializer.Deserialize(json, constructed, options);
}
public void Test()
{
this.options = new JsonSerializerOptions();
options.Converters.Add(new JsonStringEnumConverterWithAttributeSupport());
var testSerialize = JsonSerializer.Serialize(new TestEnumWrapper<ObjectClass>()
{ TestEnum = ObjectClass.RocketBody }, options);
// Test Deserialize
CanDeserialiseEnumsWithCustomJsonStrings(ObjectClass.RocketBody, "Rocket Body");
}
您只需要將new JsonStringEnumConverterWithAttributeSupport()加到 中JsonSerializerOptions.Converters即可。
如果要將轉換器用作屬性,則必須向類添加無引數建構式 JsonStringEnumConverterWithAttributeSupport
public JsonStringEnumConverterWithAttributeSupport() : this(namingPolicy : null, allowIntegerValues : true,
parseEnumMemberAttribute : true, parseDisplayAttribute : false, parseDescriptionAttribute : false)
{
}
uj5u.com熱心網友回復:
試試這個,我使用 Newtonsoft.Json 并且為了測驗我只反序列化了屬性,因為只有它們包含列舉。您不需要任何自定義代碼。
var attributes= JsonConvert.DeserializeObject<Root>(json);
班級
public enum ObjectClass
{
[EnumMember(Value = "Rocket Body")]
RocketBody,
[EnumMember(Value ="Rocket Debris")]
RocketDebris,
[EnumMember(Value = "Rocket Fragmentation Debris")]
RocketFragmentationDebris,
[EnumMember(Value ="Rocket Mission Related Object")]
RocketMissionRelatedObject
}
public partial class Root
{
[JsonProperty("attributes")]
public Attributes Attributes { get; set; }
}
public partial class Attributes
{
[JsonProperty("shape")]
public object Shape { get; set; }
[JsonProperty("xSectMin")]
public object XSectMin { get; set; }
[JsonProperty("satno")]
public object Satno { get; set; }
[JsonProperty("depth")]
public object Depth { get; set; }
[JsonProperty("objectClass")]
public ObjectClass ObjectClass { get; set; }
[JsonProperty("cosparId")]
public object CosparId { get; set; }
[JsonProperty("length")]
public object Length { get; set; }
[JsonProperty("height")]
public object Height { get; set; }
[JsonProperty("mass")]
public object Mass { get; set; }
[JsonProperty("xSectMax")]
public object XSectMax { get; set; }
[JsonProperty("vimpelId")]
public long VimpelId { get; set; }
[JsonProperty("xSectAvg")]
public object XSectAvg { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
測驗
json=JsonConvert.SerializeObject(attributes);
attributes= JsonConvert.DeserializeObject<Root>(json);
結果
{
"attributes": {
"shape": null,
"xSectMin": null,
"satno": null,
"depth": null,
"objectClass": 2,
"cosparId": null,
"length": null,
"height": null,
"mass": null,
"xSectMax": null,
"vimpelId": 84303,
"xSectAvg": null,
"name": null
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/395917.html
標籤:C# json 枚举 deserialization system.text.json
上一篇:jq映射來自不同陣列的值
下一篇:從嵌套串列中提取JSON值
