/// <summary> Clones the specified options, but omits the specified converters, if present. </summary> public static JsonSerializerOptions CloneWithout(this JsonSerializerOptions options, params JsonConverter[] convertersToRemove) { Contract.Requires(options != null); Contract.Requires(convertersToRemove != null); var result = options.Clone(); foreach (var converterToRemove in convertersToRemove) { result.Converters.Remove(converterToRemove); } return(result); }
/// <inheritdoc /> public override IAuditLogChange Read ( ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options ) { using var jsonDocument = JsonDocument.ParseValue(ref reader); if (!jsonDocument.RootElement.TryGetProperty("key", out var keyProperty)) { throw new JsonException(); } var key = keyProperty.GetString(); if (key is null) { throw new JsonException(); } if (!KeyTypes.TryGetValue(key, out var valueType)) { throw new JsonException(); } if (KeyConverters.TryGetValue(key, out var keyConverter)) { options = options.Clone(); options.Converters.Add(keyConverter); } Optional <object> newValue = default; Optional <object> oldValue = default; if (jsonDocument.RootElement.TryGetProperty("old_value", out var oldValueProperty)) { var value = JsonSerializer.Deserialize(oldValueProperty.GetRawText(), valueType, options); oldValue = value; } // ReSharper disable once InvertIf if (jsonDocument.RootElement.TryGetProperty("new_value", out var newValueProperty)) { var value = JsonSerializer.Deserialize(newValueProperty.GetRawText(), valueType, options); newValue = value; } return(new AuditLogChange(newValue, oldValue, key)); }
JsonSerializerOptions?GetJsonSerializerSettings(IJsonSerializationOptions?options = null) { if (options == null) { return(null); } var o = _options.Clone(); o.IgnoreNullValues = options.OmitNull ?? o.IgnoreNullValues; o.WriteIndented = options.Indent ?? o.WriteIndented; o.DictionaryKeyPolicy = options.CamelCaseKeys == true ? JsonNamingPolicy.CamelCase : o.DictionaryKeyPolicy; o.PropertyNamingPolicy = options.CamelCaseProperties == true ? JsonNamingPolicy.CamelCase : o.PropertyNamingPolicy; return(o); }
/// <inheritdoc /> public override void Write ( Utf8JsonWriter writer, TInterface value, JsonSerializerOptions options ) { writer.WriteStartObject(); foreach (var dtoProperty in _dtoProperties) { var propertyGetter = dtoProperty.GetGetMethod(); if (propertyGetter is null) { continue; } var propertyValue = propertyGetter.Invoke(value, new object?[] { }); if (propertyValue is IOptional optional && !optional.HasValue) { continue; } var jsonName = GetWriteJsonPropertyName(dtoProperty, options); writer.WritePropertyName(jsonName); var propertyType = dtoProperty.PropertyType; var converter = GetConverter(dtoProperty, options); if (converter is null) { JsonSerializer.Serialize(writer, propertyValue, propertyType, options); } else { // This converter should only be in effect for the duration of this property; we'll need to clone // the options. var clonedOptions = options.Clone(); clonedOptions.Converters.Add(converter); JsonSerializer.Serialize(writer, propertyValue, propertyType, clonedOptions); } } writer.WriteEndObject(); }
/// <inheritdoc /> public override TInterface Read ( ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options ) { if (reader.TokenType != JsonTokenType.StartObject) { throw new JsonException(); } if (!reader.Read()) { throw new JsonException(); } var readProperties = new Dictionary <PropertyInfo, object?>(); while (reader.TokenType != JsonTokenType.EndObject) { var propertyName = reader.GetString(); if (!reader.Read()) { throw new JsonException(); } var isPrimaryChoice = true; // Search for a property that has this JSON property's name as its primary option var dtoProperty = _dtoProperties.FirstOrDefault ( p => GetReadJsonPropertyName(p, options)[0] == propertyName ); if (dtoProperty is null) { // Allow the fallbacks to be searched as well, but mark it as just an alternative dtoProperty = _dtoProperties.FirstOrDefault ( p => GetReadJsonPropertyName(p, options).Contains(propertyName) ); if (dtoProperty is not null) { isPrimaryChoice = false; } } if (dtoProperty is null) { if (!_allowExtraProperties) { throw new JsonException(); } // No matching property - we'll skip it if (!reader.TrySkip()) { throw new JsonException("Couldn't skip elements."); } if (!reader.Read()) { throw new JsonException ( $"No matching DTO property for JSON property \"{propertyName}\" could be found." ); } continue; } var propertyType = dtoProperty.PropertyType; var converter = GetConverter(dtoProperty, options); object?propertyValue; if (converter is null) { propertyValue = JsonSerializer.Deserialize(ref reader, propertyType, options); } else { // This converter should only be in effect for the duration of this property; we'll need to clone // the options. var clonedOptions = options.Clone(); clonedOptions.Converters.Add(converter); propertyValue = JsonSerializer.Deserialize(ref reader, propertyType, clonedOptions); } // Verify nullability if (!dtoProperty.AllowsNull() && propertyValue is null) { throw new JsonException(); } if (!readProperties.ContainsKey(dtoProperty)) { readProperties.Add(dtoProperty, propertyValue); } else if (isPrimaryChoice) { readProperties[dtoProperty] = propertyValue; } if (!reader.Read()) { throw new JsonException(); } } // Reorder and polyfill the read properties var constructorArguments = new object?[_dtoProperties.Count]; for (var i = 0; i < _dtoProperties.Count; i++) { var dtoProperty = _dtoProperties[i]; if (!readProperties.TryGetValue(dtoProperty, out var propertyValue)) { if (dtoProperty.PropertyType.IsOptional()) { propertyValue = Activator.CreateInstance(dtoProperty.PropertyType); } else { throw new InvalidOperationException ( $"The data property \"{dtoProperty.Name}\" did not have a corresponding value in the JSON." ); } } constructorArguments[i] = propertyValue; } return((TInterface)_dtoConstructor.Invoke(constructorArguments)); }
public JsonSerializerFactory(JsonSerializerOptions?defaultOptions) { _options = defaultOptions?.Clone() ?? DefaultOptions; }