/// <summary> /// Converts the <see cref="JsonNode"/> representing a single JSON value into a <typeparamref name="TValue"/>. /// </summary> /// <returns>A <typeparamref name="TValue"/> representation of the JSON value.</returns> /// <param name="node">The <see cref="JsonNode"/> to convert.</param> /// <param name="jsonTypeInfo">Metadata about the type to convert.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="jsonTypeInfo"/> is <see langword="null"/>. /// </exception> /// <exception cref="JsonException"> /// <typeparamref name="TValue" /> is not compatible with the JSON. /// </exception> /// <exception cref="NotSupportedException"> /// There is no compatible <see cref="System.Text.Json.Serialization.JsonConverter"/> /// for <typeparamref name="TValue"/> or its serializable members. /// </exception> public static TValue?Deserialize <TValue>(this JsonNode?node, JsonTypeInfo <TValue> jsonTypeInfo) { if (jsonTypeInfo == null) { throw new ArgumentNullException(nameof(jsonTypeInfo)); } return(ReadUsingMetadata <TValue>(node, jsonTypeInfo)); }
/// <summary> /// Converts the <see cref="JsonNode"/> representing a single JSON value into a <typeparamref name="TValue"/>. /// </summary> /// <typeparam name="TValue">The type to deserialize the JSON value into.</typeparam> /// <returns>A <typeparamref name="TValue"/> representation of the JSON value.</returns> /// <param name="node">The <see cref="JsonNode"/> to convert.</param> /// <param name="jsonTypeInfo">Metadata about the type to convert.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="jsonTypeInfo"/> is <see langword="null"/>. /// </exception> /// <exception cref="JsonException"> /// <typeparamref name="TValue" /> is not compatible with the JSON. /// </exception> /// <exception cref="NotSupportedException"> /// There is no compatible <see cref="System.Text.Json.Serialization.JsonConverter"/> /// for <typeparamref name="TValue"/> or its serializable members. /// </exception> public static TValue?Deserialize <TValue>(this JsonNode?node, JsonTypeInfo <TValue> jsonTypeInfo) { if (jsonTypeInfo is null) { ThrowHelper.ThrowArgumentNullException(nameof(jsonTypeInfo)); } return(ReadNode <TValue>(node, jsonTypeInfo)); }
internal override void GetPath(List <string> path, JsonNode?child) { Debug.Assert(child == null); if (Parent != null) { Parent.GetPath(path, this); } }
public static object?Deserialize(this JsonNode?node, Type returnType, JsonSerializerOptions?options = null) { if (returnType == null) { throw new ArgumentNullException(nameof(returnType)); } return(ReadUsingOptions <object?>(node, returnType, options)); }
public static bool DeepEquals(JsonNode?first, JsonNode?second) { if (ReferenceEquals(first, second)) { return(true); } if (first is null && second is null) { return(true); } if (first is JsonValue firstValue && second is JsonValue secondValue) { return(DeepEquals(firstValue, secondValue)); } if (first is JsonArray firstArray && second is JsonArray secondArray) { if (firstArray.Count != secondArray.Count) { return(false); } for (var i = 0; i < firstArray.Count; i++) { if (!DeepEquals(firstArray[i], secondArray[i])) { return(false); } } return(true); } if (first is JsonObject firstObject && second is JsonObject secondObject) { if (firstObject.Count != secondObject.Count) { return(false); } foreach (var prop in firstObject) { if (!secondObject.TryGetPropertyValue(prop.Key, out var secondObjectValue)) { return(false); } if (!DeepEquals(prop.Value, secondObjectValue)) { return(false); } } return(true); } return(false); }
private void DetachParent(JsonNode?item) { InitializeIfRequired(); Debug.Assert(_dictionary != null); if (item != null) { item.Parent = null; } }
internal override void GetPath(List <string> path, JsonNode?child) { if (child != null) { int index = List.IndexOf(child); path.Add($"[{index}]"); } Parent?.GetPath(path, this); }
private void DetachParent(JsonNode?item) { if (item != null) { item.Parent = null; } // Prevent previous child from being returned from these cached variables. ClearLastValueCache(); }
public static object?Deserialize(this JsonNode?node, Type returnType, JsonSerializerOptions?options = null) { if (returnType is null) { ThrowHelper.ThrowArgumentNullException(nameof(returnType)); } JsonTypeInfo jsonTypeInfo = GetTypeInfo(options, returnType); return(ReadNode <object?>(node, jsonTypeInfo)); }
internal void SetItem(string propertyName, JsonNode?value) { if (propertyName == null) { throw new ArgumentNullException(nameof(propertyName)); } JsonNode?existing = SetNode(propertyName, value); DetachParent(existing); }
internal void SetItem(string propertyName, JsonNode?value) { if (propertyName == null) { throw new ArgumentNullException(nameof(propertyName)); } // Do a Remove+Add instead of SetItem to unparent existing value (if any). Remove(propertyName); Add(propertyName, value); }
/// <summary> /// Gets the <see cref="JsonNode"/> represented by the <paramref name="jsonElement"/>. /// Operations performed on the returned <see cref="JsonNode"/> will modify the <paramref name="jsonElement"/>. /// A return value indicates whether the operation succeeded. /// </summary> /// <param name="jsonElement"><see cref="JsonElement"/> to get the <see cref="JsonNode"/> from.</param> /// <param name="jsonNode"><see cref="JsonNode"/> represented by <paramref name="jsonElement"/>.</param> /// <returns> /// <see langword="true"/> if the operation succeded; /// otherwise, <see langword="false"/> /// </returns> public static bool TryGetNode(JsonElement jsonElement, [NotNullWhen(true)] out JsonNode?jsonNode) { if (!jsonElement.IsImmutable) { Debug.Assert(jsonElement._parent != null); jsonNode = (JsonNode)jsonElement._parent; return(true); } jsonNode = null; return(false); }
/// <summary> /// Converts the <see cref="JsonNode"/> representing a single JSON value into a <paramref name="returnType"/>. /// </summary> /// <returns>A <paramref name="returnType"/> representation of the JSON value.</returns> /// <param name="node">The <see cref="JsonNode"/> to convert.</param> /// <param name="returnType">The type of the object to convert to and return.</param> /// <param name="context">A metadata provider for serializable types.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="returnType"/> is <see langword="null"/>. /// /// -or- /// /// <paramref name="context"/> is <see langword="null"/>. /// </exception> /// <exception cref="JsonException"> /// The JSON is invalid. /// /// -or- /// /// <paramref name="returnType" /> is not compatible with the JSON. /// /// -or- /// /// There is remaining data in the string beyond a single JSON value.</exception> /// <exception cref="NotSupportedException"> /// There is no compatible <see cref="System.Text.Json.Serialization.JsonConverter"/> /// for <paramref name="returnType"/> or its serializable members. /// </exception> /// <exception cref="InvalidOperationException"> /// The <see cref="JsonSerializerContext.GetTypeInfo(Type)"/> method of the provided /// <paramref name="context"/> returns <see langword="null"/> for the type to convert. /// </exception> public static object?Deserialize(this JsonNode?node, Type returnType, JsonSerializerContext context) { if (returnType == null) { throw new ArgumentNullException(nameof(returnType)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } return(ReadUsingMetadata <object?>(node, GetTypeInfo(context, returnType))); }
private void AddChild(JsonObject node, string propertyName, JsonElement element) { var options = new JsonNodeOptions { PropertyNameCaseInsensitive = Options.PropertyNameCaseInsensitive }; JsonNode?childNode = element.ValueKind == JsonValueKind.Object ? JsonObject.Create(element, options) : element.ValueKind == JsonValueKind.Array ? JsonArray.Create(element, options) : JsonValue.Create(element, options); node[propertyName] = childNode; }
private static void AddToParent( KeyValuePair <string?, JsonNode?> nodePair, ref Stack <KeyValuePair <string?, JsonNode?> > currentNodes, ref JsonNode?toReturn, DuplicatePropertyNameHandlingStrategy duplicatePropertyNameHandling = DuplicatePropertyNameHandlingStrategy.Replace) { if (currentNodes.TryPeek(out KeyValuePair <string?, JsonNode?> parentPair)) { // Parent needs to be JsonObject or JsonArray Debug.Assert(parentPair.Value is JsonObject || parentPair.Value is JsonArray); if (parentPair.Value is JsonObject jsonObject) { Debug.Assert(nodePair.Key != null); // Handle duplicate properties accordingly to duplicatePropertyNameHandling: if (duplicatePropertyNameHandling == DuplicatePropertyNameHandlingStrategy.Replace) { jsonObject[nodePair.Key] = nodePair.Value; } else if (jsonObject._dictionary.ContainsKey(nodePair.Key)) { if (duplicatePropertyNameHandling == DuplicatePropertyNameHandlingStrategy.Error) { throw new ArgumentException(SR.JsonObjectDuplicateKey); } Debug.Assert(duplicatePropertyNameHandling == DuplicatePropertyNameHandlingStrategy.Ignore); } else { jsonObject.Add(nodePair !); } } else if (parentPair.Value is JsonArray jsonArray) { Debug.Assert(nodePair.Key == null); jsonArray.Add(nodePair.Value); } } else { // We are at the top level, so adding node to parent means setting it as returned one toReturn = nodePair.Value; } }
internal bool TrySetMemberCallback(SetMemberBinder binder, object?value) { JsonNode?node = null; if (value != null) { node = value as JsonNode; if (node == null) { node = new JsonValue <object>(value, Options); } } Dictionary[binder.Name] = node; return(true); }
private bool TrySetMemberCallback(SetMemberBinder binder, object?value) { JsonNode?node = null; if (value != null) { node = value as JsonNode; if (node == null) { node = new JsonValueNotTrimmable <object>(value, Options); } } this[binder.Name] = node; return(true); }
/// <summary> /// Converts the <see cref="JsonNode"/> representing a single JSON value into a <paramref name="returnType"/>. /// </summary> /// <returns>A <paramref name="returnType"/> representation of the JSON value.</returns> /// <param name="node">The <see cref="JsonNode"/> to convert.</param> /// <param name="returnType">The type of the object to convert to and return.</param> /// <param name="context">A metadata provider for serializable types.</param> /// <exception cref="System.ArgumentNullException"> /// <paramref name="returnType"/> is <see langword="null"/>. /// /// -or- /// /// <paramref name="context"/> is <see langword="null"/>. /// </exception> /// <exception cref="JsonException"> /// The JSON is invalid. /// /// -or- /// /// <paramref name="returnType" /> is not compatible with the JSON. /// /// -or- /// /// There is remaining data in the string beyond a single JSON value.</exception> /// <exception cref="NotSupportedException"> /// There is no compatible <see cref="System.Text.Json.Serialization.JsonConverter"/> /// for <paramref name="returnType"/> or its serializable members. /// </exception> /// <exception cref="InvalidOperationException"> /// The <see cref="JsonSerializerContext.GetTypeInfo(Type)"/> method of the provided /// <paramref name="context"/> returns <see langword="null"/> for the type to convert. /// </exception> public static object?Deserialize(this JsonNode?node, Type returnType, JsonSerializerContext context) { if (returnType == null) { throw new ArgumentNullException(nameof(returnType)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } JsonTypeInfo jsonTypeInfo = GetTypeInfo(context, returnType); return(ReadNode <object?>(node, jsonTypeInfo)); }
/// <summary> /// Returns the value of a property with the specified name. /// </summary> /// <param name="propertyName">The name of the property to return.</param> /// <param name="jsonNode">The JSON value of the property with the specified name.</param> /// <returns> /// <see langword="true"/> if a property with the specified name was found; otherwise, <see langword="false"/>. /// </returns> public bool TryGetPropertyValue(string propertyName, out JsonNode?jsonNode) { if (propertyName == _lastKey) { // Optimize for repeating sections in code: // obj.Foo.Bar.One // obj.Foo.Bar.Two jsonNode = _lastValue; return(true); } bool rc = Dictionary.TryGetValue(propertyName, out jsonNode); _lastKey = propertyName; _lastValue = jsonNode; return(rc); }
protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { Source?.Dispose(); _document = null; _jsonNode = null; Source = null; } // TODO: free unmanaged resources (unmanaged objects) and override finalizer // TODO: set large fields to null disposedValue = true; } }
protected virtual void Visit(JsonArray arr, JsonVariableVisitorContext context) { for (var i = 0; i < arr.Count; i++) { JsonNode?element = arr[i]; if (element is not null) { var index = i; context.SetValue.Push(value => { arr[index] = value; }); Visit(element, context); context.SetValue.Pop(); } } }
internal override void ReadElementAndSetProperty( object obj, string propertyName, ref Utf8JsonReader reader, JsonSerializerOptions options, ref ReadStack state) { bool success = JsonNodeConverter.Instance.TryRead(ref reader, typeof(JsonNode), options, ref state, out JsonNode? value); Debug.Assert(success); // Node converters are not resumable. Debug.Assert(obj is JsonObject); JsonObject jObject = (JsonObject)obj; Debug.Assert(value == null || value is JsonNode); JsonNode? jNodeValue = (JsonNode?)value; jObject[propertyName] = jNodeValue; }
public void Add <[DynamicallyAccessedMembers(JsonHelpers.MembersAccessedOnRead)] T>(T?value) { if (value == null) { Add(null); } else { JsonNode?jNode = value as JsonNode; if (jNode == null) { jNode = new JsonValueNotTrimmable <T>(value); } // Call the IList.Add() implementation. Add(jNode); } }
public void Add <T>(T?value) { if (value == null) { Add(null); } else { JsonNode?jNode = value as JsonNode; if (jNode == null) { jNode = new JsonValueNotTrimmable <T>(value); } // Call the IList.Add() implementation. Add(jNode); } }
internal override void GetPath(List <string> path, JsonNode?child) { if (child != null) { InitializeIfRequired(); Debug.Assert(_dictionary != null); string propertyName = _dictionary.FindValue(child) !.Value.Key; if (propertyName.IndexOfAny(ReadStack.SpecialCharacters) != -1) { path.Add($"['{propertyName}']"); } else { path.Add($".{propertyName}"); } } Parent?.GetPath(path, this); }
internal override void GetPath(List <string> path, JsonNode?child) { if (child != null) { string propertyName = FindNode(child) !.Value.Key; if (propertyName.IndexOfAny(ReadStack.SpecialCharacters) != -1) { path.Add($"['{propertyName}']"); } else { path.Add($".{propertyName}"); } } if (Parent != null) { Parent.GetPath(path, this); } }
private static TValue?ReadNode <TValue>(JsonNode?node, JsonTypeInfo jsonTypeInfo) { JsonSerializerOptions options = jsonTypeInfo.Options; // For performance, share the same buffer across serialization and deserialization. using var output = new PooledByteBufferWriter(options.DefaultBufferSize); using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions())) { if (node is null) { writer.WriteNullValue(); } else { node.WriteTo(writer, options); } } return(ReadFromSpan <TValue>(output.WrittenMemory.Span, jsonTypeInfo)); }
internal void AssignParent(JsonNode parent) { if (Parent != null) { ThrowHelper.ThrowInvalidOperationException_NodeAlreadyHasParent(); } JsonNode?p = parent; while (p != null) { if (p == this) { ThrowHelper.ThrowInvalidOperationException_NodeCycleDetected(); } p = p.Parent; } Parent = parent; }
static string ReadAsStringMetadataValue(JsonNode?jsonNode) { if (jsonNode is JsonValue jsonValue && jsonValue.TryGetValue(out string?value) && value is not null) { return(value); } JsonValueKind metadataValueKind = jsonNode switch { null => JsonValueKind.Null, JsonObject => JsonValueKind.Object, JsonArray => JsonValueKind.Array, JsonValue <JsonElement> element => element.Value.ValueKind, _ => JsonValueKind.Undefined, }; Debug.Assert(metadataValueKind != JsonValueKind.Undefined); ThrowHelper.ThrowJsonException_MetadataValueWasNotString(metadataValueKind); return(null !); }
public override void Write(Utf8JsonWriter writer, JsonNode?value, JsonSerializerOptions options) { if (value == null) { writer.WriteNullValue(); // Note JsonSerializer.Deserialize<T>(JsonNode?) also calls WriteNullValue() for a null + root JsonNode. } else { if (value is JsonValue jsonValue) { ValueConverter.Write(writer, jsonValue, options); } else if (value is JsonObject jsonObject) { ObjectConverter.Write(writer, jsonObject, options); } else { Debug.Assert(value is JsonArray); ArrayConverter.Write(writer, (JsonArray)value, options); } } }