Пользовательский сериализатор JSON для дополнительного свойства с System.text.jsonC#

Место общения программистов C#
Ответить
Anonymous
 Пользовательский сериализатор JSON для дополнительного свойства с System.text.json

Сообщение Anonymous »

Я пытаюсь реализовать механизм сериализации JSON, который обрабатывает как NULL , так и отсутствующие значения JSON, чтобы иметь возможность выполнять частичные обновления при необходимости (так что оно не касается поля в базе данных, когда значение отсутствует, но оно очищает его, когда значение явно установлено для NULL ). Тип: < /p>

Код: Выделить всё

public readonly struct Optional
{
public Optional(T value)
{
this.HasValue = true;
this.Value = value;
}

public bool HasValue { get; }
public T Value { get; }
public static implicit operator Optional(T value) => new Optional(value);
public override string ToString() => this.HasValue ? (this.Value?.ToString() ?? "null") : "unspecified";
}
Теперь я хочу иметь возможность сериализовать/десериализовать в/из JSON, чтобы любое недостающее поле в JSON сохранялось при обращении с ним через необязательный объект :

public class CustomType
{
[JsonPropertyName("foo")]
public Optional Foo { get; set; }

[JsonPropertyName("bar")]
public Optional Bar { get; set; }

[JsonPropertyName("baz")]
public Optional Baz { get; set; }
}
< /code>
Тогда: < /p>

Код: Выделить всё

var options = new JsonSerializerOptions();
options.Converters.Add(new OptionalConverter());

string json = @"{""foo"":0,""bar"":null}";
CustomType parsed = JsonSerializer.Deserialize(json, options);
string roundtrippedJson = JsonSerializer.Serialize(parsed, options);

// json and roundtrippedJson should be equivalent
Console.WriteLine("json:             " + json);
Console.WriteLine("roundtrippedJson: " + roundtrippedJson);
Я запустил реализацию, основанную на jsonconverterfactory , но я не могу найти правильный способ опустить свойство во время сериализации, если непредвиденное значение является false :

Код: Выделить всё

public class OptionalConverter : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
if (!typeToConvert.IsGenericType) { return false; }
if (typeToConvert.GetGenericTypeDefinition() != typeof(Optional)) { return false; }
return true;
}

public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
Type valueType = typeToConvert.GetGenericArguments()[0];

return (JsonConverter)Activator.CreateInstance(
type: typeof(OptionalConverterInner).MakeGenericType(new Type[] { valueType }),
bindingAttr: BindingFlags.Instance | BindingFlags.Public,
binder: null,
args: null,
culture: null
);
}

private class OptionalConverterInner : JsonConverter
{
public override Optional Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
T value = JsonSerializer.Deserialize(ref reader, options);
return new Optional(value);
}

public override void Write(Utf8JsonWriter writer, Optional value, JsonSerializerOptions options)
{
// Does not work (produces invalid JSON).
// Problem: the object's key has already been written in the JSON writer at this point.
if (value.HasValue)
{
JsonSerializer.Serialize(writer, value.Value, options);
}
}
}
}
< /code>
Проблема: это создает следующий вывод, который является недействительным: < /p>
json:             {"foo":0,"bar":null}
roundtrippedJson: {"foo":0,"bar":null,"baz":}
Как я могу это решить?


Подробнее здесь: https://stackoverflow.com/questions/634 ... -text-json
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»