将复杂的json反序列化为对象



我有一个奇怪的json,它是:

  • 我无法更改,它来自第三方
  • 它最多可以有75个属性

json:的一个简单示例

{
"bookingcode":["ABC","DEF", "GHJ", "TEST"],
"referencenumber":[123, 456]
"bookingdate":["22-07-2022T14:00:30", "23-11-2022T17:00:25"]
}

我只对数组的最后一个值感兴趣,并希望反序列化为一个名为Booking的类,因此在本例中为bookingcode="TEST"bookingdate="23-11-2022T17:00:25"

一个解决方案是定义一个模型:

public class Booking
{
public string BookingCode { get; set; }
public int ReferenceNumber { get; set; }
public DateTime BookingDate { get; set;}
}
public class BookingInput
{
public List<string> BookingCode { get; set;}
public List<int> ReferenceNumber { get; set; }
public List<DateTime> BookingDate { get; set; }
}
var bookinginput = JsonSerializer.Deserialize<BookingInput>(jsonString);
var booking = new Booking
{
BookingCode = bookinginput.BookingCode.Last(),
ReferenceNumber = bookinginput.ReferenceNumber.Last(),
...
}

我认为在这样的代码中写出所有75个属性是非常乏味的。Json.net或System.Text.Json中有更好的解决方案吗?

使用NewtonSoft.Json,您可以创建自己的JsonConverter。下面我创建了一个LastArrayItemJsonConverter,它从某个类型的数组中获取最后一项并返回。

public class LastArrayItemJsonConverter<TItem> : JsonConverter<TItem>
{
private string _formatString;

public LastArrayItemJsonConverter()
{ }

public LastArrayItemJsonConverter(string formatString)
{
_formatString = formatString;
}

public override TItem ReadJson(JsonReader reader, Type objectType, TItem existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (typeof(TItem) == typeof(DateTime) || typeof(TItem) == typeof(DateTime?))
reader.DateFormatString = _formatString;

TItem result = default;
if (reader.TokenType != JsonToken.StartArray)
return default;

while (reader.Read() && reader.TokenType != JsonToken.EndArray)
result = (TItem)Convert.ChangeType(reader.Value, typeof(TItem));

return result;
}
public override void WriteJson(JsonWriter writer, TItem value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}

通过装饰模型,您可以指定序列化程序应该使用转换器来转换属性:

public class Booking
{
[JsonConverter(typeof(LastArrayItemJsonConverter<string>))]
public string BookingCode { get; set; }
[JsonConverter(typeof(LastArrayItemJsonConverter<int>))]
public int ReferenceNumber { get; set; }
[JsonConverter(typeof(LastArrayItemJsonConverter<DateTime>), "dd-MM-yyyy\THH:mm:ss")]
public DateTime BookingDate { get; set; }
}

现在,模型的属性将用数组中的最后一个值填充。使用:反序列化json

var booking = JsonConvert.DeserializeObject<Booking>(json)

您可以定义一个包含的Booking

  • BookingInput的性质
  • 以及最后一项检索逻辑
public class Booking
{
[JsonIgnore]
public string BookingCode => BookingCodes.Last();
[JsonIgnore]
public int ReferenceNumber => ReferenceNumbers.Last();
[JsonIgnore]
public DateTime BookingDate => BookingDates.Last();
[JsonProperty("bookingcode")]
public List<string> BookingCodes { get; set; } = new List<string>();
[JsonProperty("referencenumber")]
public List<int> ReferenceNumbers { get; set; } = new List<int>();
[JsonProperty("bookingdate")]
public List<DateTime> BookingDates { get; set; } = new List<DateTime>();
}

如果您想使用自定义的c#类

using Newtonsoft.Json;
var jsonParsed = JObject.Parse(json);
foreach (var arr in jsonParsed.Properties())
jsonParsed[arr.Name] = arr.Value.LastOrDefault();
Booking booking = jsonParsed.ToObject<Booking>();

但是,由于您最多可以拥有75个属性,因此最好使用字典而不是自定义类

Dictionary<string, object> bookingDict = new Dictionary<string, object>();
foreach (var arr in jsonParsed.Properties())
bookingDict.Add(arr.Name, arr.Value.LastOrDefault());

结果

{
"bookingcode": "TEST",
"referencenumber": 456,
"bookingdate": "23-11-2022T17:00:25"
}

最好也提供请求代码。是否添加ReadAsStringAsync((;在请求之后?

public class Booking
{   
[JsonProperty("bookingcode")]
public List<string> BookingCodes { get; set; } = new List<string>();

[JsonProperty("referencenumber")]
public List<int> ReferenceNumbers { get; set; } = new List<int>();

[JsonProperty("bookingdate")]
public List<DateTime> BookingDates { get; set; } = new List<DateTime>();
}

以及一些web请求示例

using (var client = new HttpClient())
{
var response = await client.
GetAsync(apiEndpoint);
var responseText = await response.Content.ReadAsStringAsync();
var compareResult = JsonSerializer.Deserialize<Booking>(responseText)??new Booking();
return compareResult;
}

相关内容

  • 没有找到相关文章

最新更新