Но в этом подходе есть проблема: когда значения для ключа равны нулю, я не могу идти дальше в десумировании классов подгонки значений. В этих случаях я хотел бы использовать строку? в качестве типа свойства и поместить в значение свойства сериализованный вложенный JObject или JArray.
Поэтому, когда приложение выдало исключение при чтении следующее вложенное свойство:
Код: Выделить всё
.registrations[0].product_info
Код: Выделить всё
Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: {. Path '
.registrations[0].product_info', line 1, position 5138
я получил
Код: Выделить всё
{
"head_test":"------HEAD-------",
"product_info": {
"product_data": [
{
"product_xtra": {
"product_xtra_id": "",
"product_xtra_type": "",
"unit_price": "",
"vat_rate": 0.22
},
"amount": 2,
"price": ""
}
],
"product_total_price": ""
},
"tail_test":"------TAIL-------",
}
Код: Выделить всё
public class JsonObjectToStringConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
if (typeof(TValue).IsAssignableFrom(objectType))
{
return true;
}
else if(base.CanWrite)
{
return true;
}
return false;
}
public override bool CanRead => base.CanRead;
public override bool CanWrite => base.CanWrite;
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
var token = serializer.Deserialize(reader);
try
{
return token?.ToObject(objectType);
}
catch(Exception ex)
{
Log.Error(ex, "Failed to convert {token} to {objectType}", token, objectType);
return token?.ToString();
}
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if(value == null)
{
writer.WriteNull();
return;
}
try
{
var token = Newtonsoft.Json.Linq.JToken.FromObject(value);
token.WriteTo(writer);
}
catch (Exception ex)
{
Log.Error(ex, "Failed to convert {value} to json", value);
writer.WriteValue(value.ToString());
}
}
}
Вчера я проверил это, добавив атрибут в целевой класс DTO.
Код: Выделить всё
class Root{
[JsonProperty("head_test")]
public string? Head { get; set; }
[JsonProperty("product_info")]
[JsonConverter(typeof(JsonObjectToStringConverter))]
public string? ProductInfo { get; set; }
[JsonProperty("tail_test")]
public string? Tail { get; set; }
}
Я добавил сюда скрипт с рабочим фрагментом.
Код: Выделить всё
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public class Program
{
static string json = """
{
"head_test":"------HEAD-------",
"product_info": {
"product_data": [
{
"product_xtra": {
"product_xtra_id": "",
"product_xtra_type": "",
"unit_price": "",
"vat_rate": 0.22
},
"amount": 2,
"price": ""
}
],
"product_total_price": ""
},
"tail_test":"------TAIL-------",
}
""";
static string json2 = """
{
"head_test":"------HEAD-------",
"product_info": "----INFO-----",
"tail_test":"------TAIL-------",
}
""";
static string json3 = """
{
"head_test":"------HEAD-------",
"product_info": null,
"tail_test":"------TAIL-------",
}
""";
public static void Main()
{
Console.WriteLine(json);
var root = JsonConvert.DeserializeObject(json);
Console.WriteLine(root.ProductInfo ?? "");
Console.WriteLine(json2);
var root2 = JsonConvert.DeserializeObject(json2);
Console.WriteLine(root2.ProductInfo ?? "");
Console.WriteLine(json3);
var root3 = JsonConvert.DeserializeObject(json3);
Console.WriteLine(root3.ProductInfo ?? "");
}
}
class Root{
[JsonProperty("head_test")]
public string? Head { get; set; }
[JsonProperty("product_info")]
[JsonConverter(typeof(JsonObjectToStringConverter))]
public string? ProductInfo { get; set; }
[JsonProperty("tail_test")]
public string? Tail { get; set; }
}
class JsonObjectToStringConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
if (typeof(TValue).IsAssignableFrom(objectType))
{
return true;
}
else if(base.CanWrite)
{
return true;
}
return false;
}
public override bool CanRead => base.CanRead;
public override bool CanWrite => base.CanWrite;
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
var token = serializer.Deserialize(reader);
try
{
return token?.ToObject(objectType);
}
catch(Exception ex)
{
return token?.ToString();
}
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if(value == null)
{
writer.WriteNull();
return;
}
try
{
var token = Newtonsoft.Json.Linq.JToken.FromObject(value);
token.WriteTo(writer);
}
catch (Exception ex)
{
writer.WriteValue(value.ToString());
}
}
}
Код: Выделить всё
2024-11-25 22:16 +01:00: [22:16:14 ERR] Failed to convert [[[[[[[[]], [[]], [[]], [[]]]], [[]], [[]]]]], [[]]] to System.String
2024-11-25 22:16 +01:00: System.ArgumentException: Can not convert Object to String.
2024-11-25 22:16 +01:00: at Newtonsoft.Json.Linq.JToken.op_Explicit(JToken value)
2024-11-25 22:16 +01:00: at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType)
2024-11-25 22:16 +01:00: at [....].JsonConverters.JsonObjectToStringConverter`1.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer) in [...]\JsonConverters\JsonObjectToStringConverter.cs:line 37
2024-11-25 22:16 +01:00: [22:16:14 ERR] Failed to convert [[[[[[[[]], [[]], [[]], [[]]]], [[]], [[]]]]], [[]]] to System.String
2024-11-25 22:16 +01:00: System.ArgumentException: Can not convert Object to String.
2024-11-25 22:16 +01:00: at Newtonsoft.Json.Linq.JToken.op_Explicit(JToken value)
2024-11-25 22:16 +01:00: at Newtonsoft.Json.Linq.JToken.ToObject(Type objectType)
2024-11-25 22:16 +01:00: at [...].JsonConverters.JsonObjectToStringConverter`1.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer) in [...]\JsonConverters\JsonObjectToStringConverter.cs:line 37
Я прочитал вопрос «Десериализовать json с известными и неизвестными полями», в котором задается вопрос о json с неизвестными свойствами типа «_unknown_field_name_1»: «некоторое значение» , а мой json больше похож на
Код: Выделить всё
{
"id": "",
"name": "",
"product_info": null,
[...Other fields...]
}
Если я использую
Код: Выделить всё
// extra fields
[JsonExtensionData]
private IDictionary _extraStuff;
Подробнее здесь: https://stackoverflow.com/questions/792 ... own-fields