В моем приложении C# я анализирую API третьей части этого API. У меня нет какой-либо схемы или спецификаций: для анализа ответов я обычно собираю несколько ответов и пишу классы, соответствующие JSON (это может быть это легко сделать с помощью Visual Studio или онлайн с помощью JSON2CSHARP).
Но в этом подходе есть проблема: когда значения для ключа равны нулю, я не могу идти дальше в десумировании классов подгонки значений. В этих случаях я хотел бы использовать строку? в качестве типа свойства и поместить в значение свойства сериализованный вложенный JObject или JArray.
Поэтому, когда приложение выдало исключение при чтении следующее вложенное свойство:
.registrations[0].product_info
Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: {. Path '
.registrations[0].product_info', line 1, position 5138
потому что вместо «product_info»: null,
я получил
{
"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());
}
}
}
Мой вопрос: могу ли я избежать блока try/catch, чтобы проверить, можно ли нормально десериализовать объект? Как я могу это сделать?
Вчера я проверил это, добавив атрибут в целевой класс 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());
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/792 ... own-fields
Десериализация неизвестных полей NewtonSoft JSON ⇐ C#
Место общения программистов C#
-
Anonymous
1732616314
Anonymous
В моем приложении C# я анализирую API третьей части этого API. У меня нет какой-либо схемы или спецификаций: для анализа ответов я обычно собираю несколько ответов и пишу классы, соответствующие JSON (это может быть это легко сделать с помощью Visual Studio или онлайн с помощью JSON2CSHARP).
Но в этом подходе есть проблема: когда значения для ключа равны нулю, я не могу идти дальше в десумировании классов подгонки значений. В этих случаях я хотел бы использовать строку? в качестве типа свойства и поместить в значение свойства сериализованный вложенный JObject или JArray.
Поэтому, когда приложение выдало исключение при чтении следующее вложенное свойство:
.registrations[0].product_info
Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: {. Path '
.registrations[0].product_info', line 1, position 5138
потому что вместо «product_info»: null,
я получил
{
"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());
}
}
}
Мой вопрос: могу ли я избежать блока try/catch, чтобы проверить, можно ли нормально десериализовать объект? Как я могу это сделать?
Вчера я проверил это, добавив атрибут в целевой класс 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());
}
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79226240/newtonsoft-json-deserialization-of-unknown-fields[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия