/// <summary> /// Constructs a new <see cref="JsonReaderState"/> instance. /// </summary> /// <param name="options">Defines the customized behavior of the <see cref="Utf8JsonReader"/> /// that is different from the JSON RFC (for example how to handle comments or maximum depth allowed when reading). /// By default, the <see cref="Utf8JsonReader"/> follows the JSON RFC strictly (i.e. comments within the JSON are invalid) and reads up to a maximum depth of 64.</param> /// <exception cref="ArgumentException"> /// Thrown when the max depth is set to a non-positive value (< 0) /// </exception> /// <remarks> /// An instance of this state must be passed to the <see cref="Utf8JsonReader"/> ctor with the JSON data. /// Unlike the <see cref="Utf8JsonReader"/>, which is a ref struct, the state can survive /// across async/await boundaries and hence this type is required to provide support for reading /// in more data asynchronously before continuing with a new instance of the <see cref="Utf8JsonReader"/>. /// </remarks> public JsonReaderState(JsonReaderOptions options = default) { _lineNumber = default; _bytePositionInLine = default; _bytesConsumed = default; _inObject = default; _isNotPrimitive = default; _numberFormat = default; _stringHasEscaping = default; _trailingCommaBeforeComment = default; _tokenType = default; _previousTokenType = default; _readerOptions = options; // Only allocate if the user reads a JSON payload beyond the depth that the _allocationFreeContainer can handle. // This way we avoid allocations in the common, default cases, and allocate lazily. _bitStack = default; _sequencePosition = default; }
public override object?Deserialize(ReadOnlySequence <byte> input, Type type) { if (this.TraceEnabled) { this.TraceDeserialize(input, type); } var readerOptions = new JsonReaderOptions(); if (this.Options != null) { readerOptions.AllowTrailingCommas = this.Options.AllowTrailingCommas; readerOptions.CommentHandling = this.Options.ReadCommentHandling; readerOptions.MaxDepth = this.Options.MaxDepth; } ; var reader = new Utf8JsonReader(input, readerOptions); return(JsonSerializer.Deserialize(ref reader, type, this.Options)); }
/// <summary> /// Constructs a new <see cref="JsonReaderState"/> instance. /// </summary> /// <param name="maxDepth">Sets the maximum depth allowed when reading JSON, with the default set as 64. /// Reading past this depth will throw a <exception cref="JsonReaderException"/>.</param> /// <param name="options">Defines the customized behavior of the <see cref="Utf8JsonReader"/> /// that is different from the JSON RFC (for example how to handle comments). /// By default, the <see cref="Utf8JsonReader"/> follows the JSON RFC strictly (i.e. comments within the JSON are invalid).</param> /// <exception cref="ArgumentException"> /// Thrown when the max depth is set to a non-positive value (<= 0) /// </exception> /// <remarks> /// An instance of this state must be passed to the <see cref="Utf8JsonReader"/> ctor with the JSON data. /// Unlike the <see cref="Utf8JsonReader"/>, which is a ref struct, the state can survive /// across async/await boundaries and hence this type is required to provide support for reading /// in more data asynchronously before continuing with a new instance of the <see cref="Utf8JsonReader"/>. /// </remarks> public JsonReaderState(int maxDepth = DefaultMaxDepth, JsonReaderOptions options = default) { if (maxDepth <= 0) { throw ThrowHelper.GetArgumentException_MaxDepthMustBePositive(); } _lineNumber = default; _bytePositionInLine = default; _bytesConsumed = default; _maxDepth = maxDepth; _inObject = default; _isNotPrimitive = default; _tokenType = default; _previousTokenType = default; _readerOptions = options; // Only allocate if the user reads a JSON payload beyond the depth that the _allocationFreeContainer can handle. // This way we avoid allocations in the common, default cases, and allocate lazily. _bitStack = default; }
public static void ReaderOptionsWinMaxDepth() { byte[] utf8 = Encoding.UTF8.GetBytes("[[]]"); var readerOptions = new JsonReaderOptions { MaxDepth = 1, }; var serializerOptions = new JsonSerializerOptions { MaxDepth = 5, }; var state = new JsonReaderState(readerOptions); Assert.Throws <JsonException>(() => { var reader = new Utf8JsonReader(utf8, isFinalBlock: false, state); JsonSerializer.Deserialize(ref reader, typeof(int), serializerOptions); }); }
private IDictionary <string, string> ParseStream(Stream input) { _data.Clear(); var jsonReaderOptions = new JsonReaderOptions { CommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true, }; using (var reader = new StreamReader(input)) using (JsonDocument doc = JsonDocument.Parse(reader.ReadToEnd(), jsonReaderOptions)) { if (doc.RootElement.Type != JsonValueType.Object) { throw new FormatException(Resources.FormatError_UnsupportedJSONToken(doc.RootElement.Type)); } VisitElement(doc.RootElement); } return(_data); }
public static void ReaderOptionsWinTrailingCommas() { byte[] utf8 = Encoding.UTF8.GetBytes("[1, 2, 3,]"); var serializerOptions = new JsonSerializerOptions { AllowTrailingCommas = true, }; Assert.Throws <JsonException>(() => { var reader = new Utf8JsonReader(utf8); JsonSerializer.Deserialize(ref reader, typeof(int[]), serializerOptions); }); Assert.Throws <JsonException>(() => { var reader = new Utf8JsonReader(utf8, isFinalBlock: false, state: default); JsonSerializer.Deserialize(ref reader, typeof(int[]), serializerOptions); }); var readerOptions = new JsonReaderOptions { AllowTrailingCommas = true }; { var reader = new Utf8JsonReader(utf8, readerOptions); int[] result = JsonSerializer.Deserialize <int[]>(ref reader); Assert.Equal(3, result.Length); } { var reader = new Utf8JsonReader(utf8, readerOptions); int[] result = JsonSerializer.Deserialize <int[]>(ref reader, serializerOptions); Assert.Equal(3, result.Length); } }
public static void WriteIncredibleDepth() { const int TargetDepth = 500; JsonReaderOptions optionsCopy = s_readerOptions; optionsCopy.MaxDepth = TargetDepth + 1; const int SpacesPre = 12; const int SpacesSplit = 85; const int SpacesPost = 4; byte[] jsonIn = new byte[SpacesPre + TargetDepth + SpacesSplit + TargetDepth + SpacesPost]; jsonIn.AsSpan(0, SpacesPre).Fill((byte)' '); Span <byte> openBrackets = jsonIn.AsSpan(SpacesPre, TargetDepth); openBrackets.Fill((byte)'['); jsonIn.AsSpan(SpacesPre + TargetDepth, SpacesSplit).Fill((byte)' '); Span <byte> closeBrackets = jsonIn.AsSpan(SpacesPre + TargetDepth + SpacesSplit, TargetDepth); closeBrackets.Fill((byte)']'); jsonIn.AsSpan(SpacesPre + TargetDepth + SpacesSplit + TargetDepth).Fill((byte)' '); var buffer = new ArrayBufferWriter <byte>(jsonIn.Length); using (JsonDocument doc = JsonDocument.Parse(jsonIn, optionsCopy)) { var writer = new Utf8JsonWriter(buffer); doc.RootElement.WriteAsValue(writer); writer.Flush(); ReadOnlySpan <byte> formatted = buffer.WrittenSpan; Assert.Equal(TargetDepth + TargetDepth, formatted.Length); Assert.True(formatted.Slice(0, TargetDepth).SequenceEqual(openBrackets), "OpenBrackets match"); Assert.True(formatted.Slice(TargetDepth).SequenceEqual(closeBrackets), "CloseBrackets match"); } }
public void Read_ObjectWithComments_ShouldMatch(JsonCommentHandling commentHandling) { const string json = @"/* Comment */{ /* Comment */ ""a"":1, // Comment ""b"": // Comment 2, /* Comment */ ""c"": /* Comment */ 3, ""d"": [ // Comment 4/* Comment */,/* Comment */ 5 /* Comment */ ]/* Comment */ /* Comment */}"; var jsonReaderOptions = new JsonReaderOptions { CommentHandling = commentHandling, }; var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json).AsSpan(), jsonReaderOptions); reader.Read(); var converter = new ObjectConverter(); var actual = converter.Read(ref reader, typeof(object), new JsonSerializerOptions()); var expected = new Dictionary <string, object> { ["a"] = 1L, ["b"] = 2L, ["c"] = 3L, ["d"] = new List <object> { 4L, 5L }, }; JsonDeepEqualAssert.Equal(expected, actual); }
public static PhpValue Deserialize(ReadOnlySpan <byte> utf8bytes, JsonReaderOptions options, JsonDecodeOptions phpoptions) { var reader = new Utf8JsonReader(utf8bytes, options); return(ReadValue(ref reader, phpoptions)); }
/// <summary> /// Deserializes the value, sets json_last_error or throws <see cref="JsonException"/> eventually. /// </summary> public static PhpValue DeserializeWithError(Context ctx, ReadOnlySpan <byte> utf8bytes, JsonReaderOptions options, JsonDecodeOptions phpoptions) { try { var value = Deserialize(utf8bytes, options, phpoptions); SetLastJsonError(ctx, JSON_ERROR_NONE); return(value); } catch (JsonException jsonex) { if ((phpoptions & JsonDecodeOptions.JSON_THROW_ON_ERROR) == 0) { SetLastJsonError(ctx, jsonex.getCode()); return(PhpValue.Null); } else { throw; } } catch (System.Exception ex) { // internal error, // treat as syntax error if ((phpoptions & JsonDecodeOptions.JSON_THROW_ON_ERROR) == 0) { SetLastJsonError(ctx, JSON_ERROR_SYNTAX); return(PhpValue.Null); } else { throw new JsonException(ex.Message, JSON_ERROR_SYNTAX, ex as Throwable); } } }
private static LocalizationCatalog?ReadLocalizationCatalog(Stream?localizationStream, JsonReaderOptions readerOptions) { if (localizationStream == null) { return(null); } var localizationReader = new Utf8JsonStreamReader(localizationStream, readerOptions); return(ReadLocalizationCatalog(ref localizationReader)); }
public static Utf8StreamingJsonReader From(ReadOnlySequence <byte> buffer, JsonReaderOptions options, out Utf8JsonReader jsonReader) => From(new BufferReader <byte>(buffer), true, options, out jsonReader);
public static byte[] JsonLabSequenceReturnBytesHelper(byte[] data, out int length, JsonReaderOptions options = JsonReaderOptions.Default) { ReadOnlySequence <byte> sequence = CreateSegments(data); var reader = new Utf8JsonReader(sequence) { Options = options }; byte[] result = JsonLabReaderLoop(data.Length, out length, ref reader); reader.Dispose(); // TODO: Should we reset the value and valuetype once we are done? //Assert.True(reader.Value.IsEmpty); //Assert.Equal(JsonValueType.Unknown, reader.ValueType); return(result); }
public static byte[] HeapableJsonLabReturnBytesHelper(byte[] data, out int length, JsonReaderOptions options = JsonReaderOptions.Default) { var json = new Utf8Json() { Options = options }; Utf8Json.Reader reader = json.GetReader(data); return(JsonLabReaderLoop(data.Length, out length, ref reader)); }
private static Utf8StreamingJsonReader From(IBufferReader <byte> reader, bool dispose, JsonReaderOptions options, out Utf8JsonReader jsonReader) { var Reader = new Utf8StreamingJsonReader(reader, dispose); jsonReader = Reader.GetInitialReader(options); return(Reader); }
public static Utf8StreamingJsonReader From(IBufferReader <byte> reader, JsonReaderOptions options, out Utf8JsonReader jsonReader) => From(reader, false, options, out jsonReader);
public async Task <(bool success, bool noValue, object model, Exception exception)> ReadAsync(FromBodyPropertyInputFormatterContext context, Func <Func <Stream, JsonSerializerOptions, Task>, Task> readRequestBody, Encoding encoding) { if (!string.Equals(_actionId, context.ActionId, StringComparison.Ordinal)) { throw new InvalidOperationException("Invalid action '" + context.ActionId + "', initialize for action '" + _actionId + "'."); } if (!HasReadRequestBody) { HasReadRequestBody = true; await readRequestBody(async (s, options) => { _options = options; int bufferSize = 0x4096; var propertyData = new Dictionary <string, List <byte[]> >(StringComparer.Ordinal); var readerOptions = new JsonReaderOptions { AllowTrailingCommas = options.AllowTrailingCommas, CommentHandling = options.ReadCommentHandling, MaxDepth = options.MaxDepth }; var readerState = new JsonReaderState(readerOptions); var buffer = ArrayPool <byte> .Shared.Rent(bufferSize); Memory <byte> memory = buffer.AsMemory(0, bufferSize); int length; int offset = 0; string currentProperty = null; int depth = 0; DataBlockMode blockMode = DataBlockMode.Start; bool handled = false; bool finalBlock = false; int consumed = 0; try { length = await s.ReadAsync(memory); finalBlock = length == 0; do { (handled, consumed) = HandleDataBlock(context, ref blockMode, ref depth, ref readerState, memory.Span.Slice(offset, length), finalBlock, ref currentProperty, propertyData); offset += consumed; if (!handled) { int bytesInBuffer = length - offset; if (bytesInBuffer == 0) { // read more data length = await s.ReadAsync(memory); finalBlock = length == 0; offset = 0; } else if ((uint)bytesInBuffer > ((uint)bufferSize / 2)) { // expand buffer bufferSize = (bufferSize < (int.MaxValue / 2)) ? bufferSize * 2 : int.MaxValue; var buffer2 = ArrayPool <byte> .Shared.Rent(bufferSize); // copy the unprocessed data Buffer.BlockCopy(buffer, offset, buffer2, 0, bytesInBuffer); // return previous buffer ArrayPool <byte> .Shared.Return(buffer); buffer = buffer2; memory = buffer.AsMemory(0, bufferSize); // read more data length = await s.ReadAsync(memory.Slice(bytesInBuffer)); finalBlock = length == 0; length += bytesInBuffer; offset = 0; } else { Buffer.BlockCopy(buffer, offset, buffer, 0, bytesInBuffer); // read more data length = await s.ReadAsync(memory.Slice(bytesInBuffer)); finalBlock = length == 0; length += bytesInBuffer; offset = 0; } } }while (!handled); } finally { ArrayPool <byte> .Shared.Return(buffer); } foreach ((var key, var value) in propertyData) { _values.Add(key, value.SelectMany(z => z).ToArray()); } }); } if (!_keys.TryGetValue(context.FieldName, out var propertyType)) { throw new InvalidOperationException("Unknown property '" + context.FieldName + "' requested."); } else if (_values.TryGetValue(context.FieldName, out var propertyData)) { try { var v = JsonSerializer.Deserialize(propertyData, propertyType, _options); return(true, false, v, null); } catch (Exception ex) { return(false, false, null, ex); } } return(true, true, null, null); }
/// <summary> /// Configures the <see cref="JsonReaderOptions"/> to use. /// </summary> /// <param name="config">The <see cref="SerializationExtensions{T}"/> instance.</param> /// <param name="options">The <see cref="JsonReaderOptions"/> to use.</param> public static void ReaderOptions(this SerializationExtensions <SystemJsonSerializer> config, JsonReaderOptions options) { Guard.AgainstNull(config, nameof(config)); Guard.AgainstNull(options, nameof(options)); var settings = config.GetSettings(); settings.Set(options); }