我试图访问一个API,并得到下面的响应体与邮差:
{
"Name": "wangxiaoer",
"Created": "2018-01-26T01:28:19.0388857Z",
"Modified": "2019-06-18T03:46:52.4350569Z",
"AdminSecurityGroups": "mhanch;sastrys;vinala;vballa",
"DeveloperOwner": "sastrys;vballa",
"ProgramManagerOwner": "sastrys",
"Comments": null
}
我使用了下面的代码:
var content = await httpResponse.Content.ReadAsStringAsync();
获取响应体
我想将这个内容反序列化为一个自定义对象,如下所示:
class MyObject
{
public string Name{get;set}
[JsonProperty(PropertyName = "AdminSecurityGroups")]
public List<String> Admins { get; set; }
[JsonProperty(PropertyName = "DeveloperOwner")]
public List<String> DevOwner { get; set; }
[JsonProperty(PropertyName = "ProgramManagerOwner")]
public List<String> PMOwner { get; set; }
}
由于响应内容为我提供了由AdminSecurityGroups, DeveloperOwner, ProgramManagerOwner的';'分割的多个人的别名组成的每个字符串,因此最好将每个字符串转换为列表,以便以后重用它。我试图在对象中定义一个列表,而不是使用String来存储这些部分,但是当我使用
时MyObject my = JsonConvert.DeserializeObject<MyObject>(content);
抛出异常。当使用c#解析json字符串时,是否有方法实现将字符串转换为列表?例如:
"AdminSecurityGroups": "mhanch;sastrys;vinala;vballa"
通过分裂包含4个人;当获得响应字符串时。需要将其解析为列表
您可以通过多种方式做到这一点,
-
规范化json, json有数组....
-
反序列化为字符串,然后使用另一个属性拆分它,或者映射到另一个属性。
-
只需使用转换器,它是为这种情况构建的
Json。
public class MyObject
{
public string Name{get; set; }
[JsonProperty( "AdminSecurityGroups")]
[JsonConverter(typeof(MyFunkConverter))]
public List<string> Admins { get; set; }
[JsonProperty( "DeveloperOwner")]
[JsonConverter(typeof(MyFunkConverter))]
public List<string> DevOwner { get; set; }
[JsonProperty( "ProgramManagerOwner")]
[JsonConverter(typeof(MyFunkConverter))]
public List<string> PMOwner { get; set; }
}
public class MyFunkConverter : JsonConverter<List<string>>
{
public override void WriteJson(JsonWriter writer, List<string> value, JsonSerializer serializer)
=> throw new NotImplementedException();
public override List<string> ReadJson(JsonReader reader, Type objectType, List<string> existingValue, bool hasExistingValue, JsonSerializer serializer) =>
reader.Value.ToString().Split(';').ToList();
}
...
var result = JsonConvert.DeserializeObject<MyObject>(input);
文本。Json
public class MyObject
{
public string Name{get; set; }
[JsonPropertyName("AdminSecurityGroups")]
[JsonConverter(typeof(MyFunkConverter))]
public List<string> Admins { get; set; }
[JsonPropertyName("DeveloperOwner")]
[JsonConverter(typeof(MyFunkConverter))]
public List<string> DevOwner { get; set; }
[JsonPropertyName( "ProgramManagerOwner")]
[JsonConverter(typeof(MyFunkConverter))]
public List<string> PMOwner { get; set; }
}
public class MyFunkConverter : System.Text.Json.Serialization.JsonConverter<List<string>>
{
public override List<string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
=> reader.GetString().Split(';').ToList();
public override void Write(Utf8JsonWriter writer, List<string> value, JsonSerializerOptions options)
=> throw new NotImplementedException();
}
...
var result = JsonSerializer.Deserialize<MyObject>(input);
这里有一个更简单的方法。只需将JSON反序列化为对象,并通过只读属性将这些字符串作为集合公开。
这样做的优点是将原始(分号完整的)字符串公开为属性(如果有人想看到它们)。事实上,那些我使用你的属性名称,我可能会重命名Admins,DeveloperOwnerRaw和PmOwner到AdminSecurityGroupsRaw,DeveloperOwnerRaw和ProgramManagerOwnerRaw如果这是我的代码。
首先扩展您的MyObject
类(我给了它一个更具描述性的名称):
public class JsonStringToArrayObject
{
public string Name { get; set; }
[JsonProperty(PropertyName = "AdminSecurityGroups")]
public string Admins { get; set; }
[JsonProperty(PropertyName = "DeveloperOwner")]
public string DevOwner { get; set; }
[JsonProperty(PropertyName = "ProgramManagerOwner")]
public string PmOwner { get; set; }
private List<string> _adminSecurityGroups = null;
private List<string> _developerOwner = null;
private List<string> _programManagerOwner = null;
[JsonIgnore]
public IEnumerable<string> AdminSecurityGroups
{
get
{
if (_adminSecurityGroups == null && !string.IsNullOrWhiteSpace(Admins))
{
_adminSecurityGroups = Admins.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
}
return _adminSecurityGroups;
}
}
[JsonIgnore]
public IEnumerable<string> DeveloperOwner
{
get
{
if (_developerOwner == null && !string.IsNullOrWhiteSpace(DevOwner))
{
_developerOwner = DevOwner.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
}
return _developerOwner;
}
}
[JsonIgnore]
public IEnumerable<string> ProgramManagerOwner
{
get
{
if (_programManagerOwner == null && !string.IsNullOrWhiteSpace(PmOwner))
{
_programManagerOwner = PmOwner.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
}
return _programManagerOwner;
}
}
}
json公开的属性是相同的。但是,我添加了只读属性,将分号分隔的字符串公开为数组。这些getter的代码重复了三次,您可能希望将其重构为一个小的worker函数。
执行此操作的代码很简单,首先是JSON(我使用单引号-在c#中更容易):
private const string theJson = @"
{
'Name': 'wangxiaoer',
'Created': '2018-01-26T01:28:19.0388857Z',
'Modified': '2019-06-18T03:46:52.4350569Z',
'AdminSecurityGroups': 'mhanch;sastrys;vinala;vballa',
'DeveloperOwner': 'sastrys;vballa',
'ProgramManagerOwner': 'sastrys',
'Comments': null
}";
然后是这个:
var jsonStringToArrayObject = JsonConvert.DeserializeObject<JsonStringToArrayObject>(theJson);
在类似的代码执行之后,我可以在调试器中看到以下内容:
- AdminSecurityGroups Count = 4
[0] "mhanch" string
[1] "sastrys" string
[2] "vinala" string
[3] "vballa" string
和
- DeveloperOwner Count = 2
[0] "sastrys" string
[1] "vballa" string
和
- ProgramManagerOwner Count = 1
[0] "sastrys" string
那个重复的代码把我逼疯了。所以我做了一点重构,将这个私有方法添加到
JsonStringToArrayObject
:
private IEnumerable<string> GetterImplementation(ref List<string> privateField, string source)
{
if (privateField == null && !string.IsNullOrWhiteSpace(source))
{
privateField = source.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
}
return privateField;
}
那么这三个只读属性的结尾是:
[JsonIgnore]
public IEnumerable<string> AdminSecurityGroups => GetterImplementation(ref _adminSecurityGroups, Admins);
[JsonIgnore]
public IEnumerable<string> DeveloperOwner => GetterImplementation(ref _developerOwner, DevOwner);
[JsonIgnore]
public IEnumerable<string> ProgramManagerOwner => GetterImplementation(ref _programManagerOwner, PmOwner);
和其他东西都是一样的