chore: fixed lib version

oneRain 2021-03-30 10:54:25 +08:00
parent 7592688aae
commit c14ac61e59
182 changed files with 2382 additions and 3401 deletions

View File

@ -13,8 +13,6 @@
<Folder Include="Exception\" /> <Folder Include="Exception\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Libs\Newtonsoft.Json\LC.Newtonsoft.Json.csproj"> <ProjectReference Include="..\..\Libs\Newtonsoft.Json\LC.Newtonsoft.Json.csproj" />
<ReferenceSourceTarget>ProjectReference</ReferenceSourceTarget>
</ProjectReference>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -34,7 +34,6 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
using System.Security; using System.Security;
using System.Text; using System.Text;
#if !NET35 #if !NET35
@ -50,36 +49,40 @@ namespace LC.Google.Protobuf
/// <summary> /// <summary>
/// Immutable array of bytes. /// Immutable array of bytes.
/// </summary> /// </summary>
[SecuritySafeCritical]
public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString> public sealed class ByteString : IEnumerable<byte>, IEquatable<ByteString>
{ {
private static readonly ByteString empty = new ByteString(new byte[0]); private static readonly ByteString empty = new ByteString(new byte[0]);
private readonly ReadOnlyMemory<byte> bytes; private readonly byte[] bytes;
/// <summary> /// <summary>
/// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance. /// Unsafe operations that can cause IO Failure and/or other catastrophic side-effects.
/// </summary> /// </summary>
internal static ByteString AttachBytes(ReadOnlyMemory<byte> bytes) internal static class Unsafe
{
/// <summary>
/// Constructs a new ByteString from the given byte array. The array is
/// *not* copied, and must not be modified after this constructor is called.
/// </summary>
internal static ByteString FromBytes(byte[] bytes)
{
return new ByteString(bytes);
}
}
/// <summary>
/// Internal use only. Ensure that the provided array is not mutated and belongs to this instance.
/// </summary>
internal static ByteString AttachBytes(byte[] bytes)
{ {
return new ByteString(bytes); return new ByteString(bytes);
} }
/// <summary> /// <summary>
/// Internal use only. Ensure that the provided memory is not mutated and belongs to this instance. /// Constructs a new ByteString from the given byte array. The array is
/// This method encapsulates converting array to memory. Reduces need for SecuritySafeCritical
/// in .NET Framework.
/// </summary>
internal static ByteString AttachBytes(byte[] bytes)
{
return AttachBytes(bytes.AsMemory());
}
/// <summary>
/// Constructs a new ByteString from the given memory. The memory is
/// *not* copied, and must not be modified after this constructor is called. /// *not* copied, and must not be modified after this constructor is called.
/// </summary> /// </summary>
private ByteString(ReadOnlyMemory<byte> bytes) private ByteString(byte[] bytes)
{ {
this.bytes = bytes; this.bytes = bytes;
} }
@ -108,13 +111,18 @@ namespace LC.Google.Protobuf
get { return Length == 0; } get { return Length == 0; }
} }
#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY
/// <summary> /// <summary>
/// Provides read-only access to the data of this <see cref="ByteString"/>. /// Provides read-only access to the data of this <see cref="ByteString"/>.
/// No data is copied so this is the most efficient way of accessing. /// No data is copied so this is the most efficient way of accessing.
/// </summary> /// </summary>
public ReadOnlySpan<byte> Span public ReadOnlySpan<byte> Span
{ {
get { return bytes.Span; } [SecuritySafeCritical]
get
{
return new ReadOnlySpan<byte>(bytes);
}
} }
/// <summary> /// <summary>
@ -123,8 +131,13 @@ namespace LC.Google.Protobuf
/// </summary> /// </summary>
public ReadOnlyMemory<byte> Memory public ReadOnlyMemory<byte> Memory
{ {
get { return bytes; } [SecuritySafeCritical]
get
{
return new ReadOnlyMemory<byte>(bytes);
}
} }
#endif
/// <summary> /// <summary>
/// Converts this <see cref="ByteString"/> into a byte array. /// Converts this <see cref="ByteString"/> into a byte array.
@ -133,7 +146,7 @@ namespace LC.Google.Protobuf
/// <returns>A byte array with the same data as this <c>ByteString</c>.</returns> /// <returns>A byte array with the same data as this <c>ByteString</c>.</returns>
public byte[] ToByteArray() public byte[] ToByteArray()
{ {
return bytes.ToArray(); return (byte[]) bytes.Clone();
} }
/// <summary> /// <summary>
@ -142,16 +155,7 @@ namespace LC.Google.Protobuf
/// <returns>A base64 representation of this <c>ByteString</c>.</returns> /// <returns>A base64 representation of this <c>ByteString</c>.</returns>
public string ToBase64() public string ToBase64()
{ {
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment)) return Convert.ToBase64String(bytes);
{
// Fast path. ByteString was created with an array, so pass the underlying array.
return Convert.ToBase64String(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array. Convert memory and pass result to ToBase64String.
return Convert.ToBase64String(bytes.ToArray());
}
} }
/// <summary> /// <summary>
@ -195,10 +199,21 @@ namespace LC.Google.Protobuf
/// <param name="stream">The stream to copy into a ByteString.</param> /// <param name="stream">The stream to copy into a ByteString.</param>
/// <param name="cancellationToken">The cancellation token to use when reading from the stream, if any.</param> /// <param name="cancellationToken">The cancellation token to use when reading from the stream, if any.</param>
/// <returns>A ByteString with content read from the given stream.</returns> /// <returns>A ByteString with content read from the given stream.</returns>
public static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken)) public async static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{ {
ProtoPreconditions.CheckNotNull(stream, nameof(stream)); ProtoPreconditions.CheckNotNull(stream, nameof(stream));
return ByteStringAsync.FromStreamAsyncCore(stream, cancellationToken); int capacity = stream.CanSeek ? checked((int) (stream.Length - stream.Position)) : 0;
var memoryStream = new MemoryStream(capacity);
// We have to specify the buffer size here, as there's no overload accepting the cancellation token
// alone. But it's documented to use 81920 by default if not specified.
await stream.CopyToAsync(memoryStream, 81920, cancellationToken);
#if NETSTANDARD1_1 || NETSTANDARD2_0
byte[] bytes = memoryStream.ToArray();
#else
// Avoid an extra copy if we can.
byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();
#endif
return AttachBytes(bytes);
} }
#endif #endif
@ -224,15 +239,18 @@ namespace LC.Google.Protobuf
return new ByteString(portion); return new ByteString(portion);
} }
#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY
/// <summary> /// <summary>
/// Constructs a <see cref="ByteString" /> from a read only span. The contents /// Constructs a <see cref="ByteString" /> from a read only span. The contents
/// are copied, so further modifications to the span will not /// are copied, so further modifications to the span will not
/// be reflected in the returned <see cref="ByteString" />. /// be reflected in the returned <see cref="ByteString" />.
/// </summary> /// </summary>
[SecuritySafeCritical]
public static ByteString CopyFrom(ReadOnlySpan<byte> bytes) public static ByteString CopyFrom(ReadOnlySpan<byte> bytes)
{ {
return new ByteString(bytes.ToArray()); return new ByteString(bytes.ToArray());
} }
#endif
/// <summary> /// <summary>
/// Creates a new <see cref="ByteString" /> by encoding the specified text with /// Creates a new <see cref="ByteString" /> by encoding the specified text with
@ -256,7 +274,7 @@ namespace LC.Google.Protobuf
/// </summary> /// </summary>
public byte this[int index] public byte this[int index]
{ {
get { return bytes.Span[index]; } get { return bytes[index]; }
} }
/// <summary> /// <summary>
@ -270,18 +288,7 @@ namespace LC.Google.Protobuf
/// <returns>The result of decoding the binary data with the given decoding.</returns> /// <returns>The result of decoding the binary data with the given decoding.</returns>
public string ToString(Encoding encoding) public string ToString(Encoding encoding)
{ {
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment)) return encoding.GetString(bytes, 0, bytes.Length);
{
// Fast path. ByteString was created with an array.
return encoding.GetString(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array. Convert memory and pass result to GetString.
// TODO: Consider using GetString overload that takes a pointer.
byte[] array = bytes.ToArray();
return encoding.GetString(array, 0, array.Length);
}
} }
/// <summary> /// <summary>
@ -301,10 +308,9 @@ namespace LC.Google.Protobuf
/// Returns an iterator over the bytes in this <see cref="ByteString"/>. /// Returns an iterator over the bytes in this <see cref="ByteString"/>.
/// </summary> /// </summary>
/// <returns>An iterator over the bytes in this object.</returns> /// <returns>An iterator over the bytes in this object.</returns>
[SecuritySafeCritical]
public IEnumerator<byte> GetEnumerator() public IEnumerator<byte> GetEnumerator()
{ {
return MemoryMarshal.ToEnumerable(bytes).GetEnumerator(); return ((IEnumerable<byte>) bytes).GetEnumerator();
} }
/// <summary> /// <summary>
@ -322,17 +328,7 @@ namespace LC.Google.Protobuf
public CodedInputStream CreateCodedInput() public CodedInputStream CreateCodedInput()
{ {
// We trust CodedInputStream not to reveal the provided byte array or modify it // We trust CodedInputStream not to reveal the provided byte array or modify it
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment) && segment.Count == bytes.Length) return new CodedInputStream(bytes);
{
// Fast path. ByteString was created with a complete array.
return new CodedInputStream(segment.Array);
}
else
{
// Slow path. BytesString is not an array, or is a slice of an array.
// Convert memory and pass result to WriteRawBytes.
return new CodedInputStream(bytes.ToArray());
}
} }
/// <summary> /// <summary>
@ -351,8 +347,18 @@ namespace LC.Google.Protobuf
{ {
return false; return false;
} }
if (lhs.bytes.Length != rhs.bytes.Length)
return lhs.bytes.Span.SequenceEqual(rhs.bytes.Span); {
return false;
}
for (int i = 0; i < lhs.Length; i++)
{
if (rhs.bytes[i] != lhs.bytes[i])
{
return false;
}
}
return true;
} }
/// <summary> /// <summary>
@ -371,7 +377,6 @@ namespace LC.Google.Protobuf
/// </summary> /// </summary>
/// <param name="obj">The object to compare this with.</param> /// <param name="obj">The object to compare this with.</param>
/// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <see cref="ByteString"/>; <c>false</c> otherwise.</returns> /// <returns><c>true</c> if <paramref name="obj"/> refers to an equal <see cref="ByteString"/>; <c>false</c> otherwise.</returns>
[SecuritySafeCritical]
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return this == (obj as ByteString); return this == (obj as ByteString);
@ -382,15 +387,12 @@ namespace LC.Google.Protobuf
/// will return the same hash code. /// will return the same hash code.
/// </summary> /// </summary>
/// <returns>A hash code for this object.</returns> /// <returns>A hash code for this object.</returns>
[SecuritySafeCritical]
public override int GetHashCode() public override int GetHashCode()
{ {
ReadOnlySpan<byte> b = bytes.Span;
int ret = 23; int ret = 23;
for (int i = 0; i < b.Length; i++) foreach (byte b in bytes)
{ {
ret = (ret * 31) + b[i]; ret = (ret * 31) + b;
} }
return ret; return ret;
} }
@ -405,12 +407,20 @@ namespace LC.Google.Protobuf
return this == other; return this == other;
} }
/// <summary>
/// Used internally by CodedOutputStream to avoid creating a copy for the write
/// </summary>
internal void WriteRawBytesTo(CodedOutputStream outputStream)
{
outputStream.WriteRawBytes(bytes, 0, bytes.Length);
}
/// <summary> /// <summary>
/// Copies the entire byte array to the destination array provided at the offset specified. /// Copies the entire byte array to the destination array provided at the offset specified.
/// </summary> /// </summary>
public void CopyTo(byte[] array, int position) public void CopyTo(byte[] array, int position)
{ {
bytes.CopyTo(array.AsMemory(position)); ByteArray.Copy(bytes, 0, array, position, bytes.Length);
} }
/// <summary> /// <summary>
@ -418,17 +428,7 @@ namespace LC.Google.Protobuf
/// </summary> /// </summary>
public void WriteTo(Stream outputStream) public void WriteTo(Stream outputStream)
{ {
if (MemoryMarshal.TryGetArray(bytes, out ArraySegment<byte> segment)) outputStream.Write(bytes, 0, bytes.Length);
{
// Fast path. ByteString was created with an array, so pass the underlying array.
outputStream.Write(segment.Array, segment.Offset, segment.Count);
}
else
{
// Slow path. BytesString is not an array. Convert memory and pass result to WriteRawBytes.
var array = bytes.ToArray();
outputStream.Write(array, 0, array.Length);
}
} }
} }
} }

View File

@ -1,64 +0,0 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace LC.Google.Protobuf
{
/// <summary>
/// SecuritySafeCritical attribute can not be placed on types with async methods.
/// This class has ByteString's async methods so it can be marked with SecuritySafeCritical.
/// </summary>
internal static class ByteStringAsync
{
#if !NET35
internal static async Task<ByteString> FromStreamAsyncCore(Stream stream, CancellationToken cancellationToken)
{
int capacity = stream.CanSeek ? checked((int)(stream.Length - stream.Position)) : 0;
var memoryStream = new MemoryStream(capacity);
// We have to specify the buffer size here, as there's no overload accepting the cancellation token
// alone. But it's documented to use 81920 by default if not specified.
await stream.CopyToAsync(memoryStream, 81920, cancellationToken);
#if NETSTANDARD1_1
byte[] bytes = memoryStream.ToArray();
#else
// Avoid an extra copy if we can.
byte[] bytes = memoryStream.Length == memoryStream.Capacity ? memoryStream.GetBuffer() : memoryStream.ToArray();
#endif
return ByteString.AttachBytes(bytes);
}
#endif
}
}

View File

@ -448,10 +448,12 @@ namespace LC.Google.Protobuf.Collections
[SecuritySafeCritical] [SecuritySafeCritical]
public void AddEntriesFrom(ref ParseContext ctx, Codec codec) public void AddEntriesFrom(ref ParseContext ctx, Codec codec)
{ {
var adapter = new Codec.MessageAdapter(codec);
do do
{ {
KeyValuePair<TKey, TValue> entry = ParsingPrimitivesMessages.ReadMapEntry(ref ctx, codec); adapter.Reset();
this[entry.Key] = entry.Value; ctx.ReadMessage(adapter);
this[adapter.Key] = adapter.Value;
} while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, codec.MapTag)); } while (ParsingPrimitives.MaybeConsumeTag(ref ctx.buffer, ref ctx.state, codec.MapTag));
} }
@ -483,13 +485,13 @@ namespace LC.Google.Protobuf.Collections
[SecuritySafeCritical] [SecuritySafeCritical]
public void WriteTo(ref WriteContext ctx, Codec codec) public void WriteTo(ref WriteContext ctx, Codec codec)
{ {
var message = new Codec.MessageAdapter(codec);
foreach (var entry in list) foreach (var entry in list)
{ {
message.Key = entry.Key;
message.Value = entry.Value;
ctx.WriteTag(codec.MapTag); ctx.WriteTag(codec.MapTag);
ctx.WriteMessage(message);
WritingPrimitives.WriteLength(ref ctx.buffer, ref ctx.state, CalculateEntrySize(codec, entry));
codec.KeyCodec.WriteTagAndValue(ref ctx, entry.Key);
codec.ValueCodec.WriteTagAndValue(ref ctx, entry.Value);
} }
} }
@ -504,22 +506,18 @@ namespace LC.Google.Protobuf.Collections
{ {
return 0; return 0;
} }
var message = new Codec.MessageAdapter(codec);
int size = 0; int size = 0;
foreach (var entry in list) foreach (var entry in list)
{ {
int entrySize = CalculateEntrySize(codec, entry); message.Key = entry.Key;
message.Value = entry.Value;
size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag); size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag);
size += CodedOutputStream.ComputeLengthSize(entrySize) + entrySize; size += CodedOutputStream.ComputeMessageSize(message);
} }
return size; return size;
} }
private static int CalculateEntrySize(Codec codec, KeyValuePair<TKey, TValue> entry)
{
return codec.KeyCodec.CalculateSizeWithTag(entry.Key) + codec.ValueCodec.CalculateSizeWithTag(entry.Value);
}
/// <summary> /// <summary>
/// Returns a string representation of this repeated field, in the same /// Returns a string representation of this repeated field, in the same
/// way as it would be represented by the default JSON formatter. /// way as it would be represented by the default JSON formatter.
@ -656,20 +654,101 @@ namespace LC.Google.Protobuf.Collections
this.mapTag = mapTag; this.mapTag = mapTag;
} }
/// <summary>
/// The key codec.
/// </summary>
internal FieldCodec<TKey> KeyCodec => keyCodec;
/// <summary>
/// The value codec.
/// </summary>
internal FieldCodec<TValue> ValueCodec => valueCodec;
/// <summary> /// <summary>
/// The tag used in the enclosing message to indicate map entries. /// The tag used in the enclosing message to indicate map entries.
/// </summary> /// </summary>
internal uint MapTag => mapTag; internal uint MapTag { get { return mapTag; } }
/// <summary>
/// A mutable message class, used for parsing and serializing. This
/// delegates the work to a codec, but implements the <see cref="IMessage"/> interface
/// for interop with <see cref="CodedInputStream"/> and <see cref="CodedOutputStream"/>.
/// This is nested inside Codec as it's tightly coupled to the associated codec,
/// and it's simpler if it has direct access to all its fields.
/// </summary>
internal class MessageAdapter : IMessage, IBufferMessage
{
private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 };
private readonly Codec codec;
internal TKey Key { get; set; }
internal TValue Value { get; set; }
internal MessageAdapter(Codec codec)
{
this.codec = codec;
}
internal void Reset()
{
Key = codec.keyCodec.DefaultValue;
Value = codec.valueCodec.DefaultValue;
}
public void MergeFrom(CodedInputStream input)
{
// Message adapter is an internal class and we know that all the parsing will happen via InternalMergeFrom.
throw new NotImplementedException();
}
[SecuritySafeCritical]
public void InternalMergeFrom(ref ParseContext ctx)
{
uint tag;
while ((tag = ctx.ReadTag()) != 0)
{
if (tag == codec.keyCodec.Tag)
{
Key = codec.keyCodec.Read(ref ctx);
}
else if (tag == codec.valueCodec.Tag)
{
Value = codec.valueCodec.Read(ref ctx);
}
else
{
ParsingPrimitivesMessages.SkipLastField(ref ctx.buffer, ref ctx.state);
}
}
// Corner case: a map entry with a key but no value, where the value type is a message.
// Read it as if we'd seen input with no data (i.e. create a "default" message).
if (Value == null)
{
if (ctx.state.CodedInputStream != null)
{
// the decoded message might not support parsing from ParseContext, so
// we need to allow fallback to the legacy MergeFrom(CodedInputStream) parsing.
Value = codec.valueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData));
}
else
{
ParseContext.Initialize(new ReadOnlySequence<byte>(ZeroLengthMessageStreamData), out ParseContext zeroLengthCtx);
Value = codec.valueCodec.Read(ref zeroLengthCtx);
}
}
}
public void WriteTo(CodedOutputStream output)
{
// Message adapter is an internal class and we know that all the writing will happen via InternalWriteTo.
throw new NotImplementedException();
}
[SecuritySafeCritical]
public void InternalWriteTo(ref WriteContext ctx)
{
codec.keyCodec.WriteTagAndValue(ref ctx, Key);
codec.valueCodec.WriteTagAndValue(ref ctx, Value);
}
public int CalculateSize()
{
return codec.keyCodec.CalculateSizeWithTag(Key) + codec.valueCodec.CalculateSizeWithTag(Value);
}
MessageDescriptor IMessage.Descriptor { get { return null; } }
}
} }
private class MapView<T> : ICollection<T>, ICollection private class MapView<T> : ICollection<T>, ICollection

View File

@ -59,7 +59,7 @@ namespace LC.Google.Protobuf
public int CalculateSize() public int CalculateSize()
{ {
return codec.CalculateUnconditionalSizeWithTag(field); return codec.CalculateSizeWithTag(field);
} }
public IExtensionValue Clone() public IExtensionValue Clone()

View File

@ -876,12 +876,6 @@ namespace LC.Google.Protobuf
/// </summary> /// </summary>
public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize; public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize;
/// <summary>
/// Calculates the size required to write the given value, with a tag, even
/// if the value is the default.
/// </summary>
internal int CalculateUnconditionalSizeWithTag(T value) => ValueSizeCalculator(value) + tagSize;
private bool IsDefault(T value) => EqualityComparer.Equals(value, DefaultValue); private bool IsDefault(T value) => EqualityComparer.Equals(value, DefaultValue);
} }
} }

View File

@ -32,6 +32,7 @@
namespace LC.Google.Protobuf namespace LC.Google.Protobuf
{ {
#if GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY
/// <summary> /// <summary>
/// Interface for a Protocol Buffers message, supporting /// Interface for a Protocol Buffers message, supporting
/// parsing from <see cref="ParseContext"/> and writing to <see cref="WriteContext"/>. /// parsing from <see cref="ParseContext"/> and writing to <see cref="WriteContext"/>.
@ -50,4 +51,5 @@ namespace LC.Google.Protobuf
/// </summary> /// </summary>
void InternalWriteTo(ref WriteContext ctx); void InternalWriteTo(ref WriteContext ctx);
} }
#endif
} }

View File

@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description> <Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description>
<Copyright>Copyright 2015, Google Inc.</Copyright> <Copyright>Copyright 2015, Google Inc.</Copyright>
<AssemblyTitle>Google Protocol Buffers</AssemblyTitle> <AssemblyTitle>Google Protocol Buffers</AssemblyTitle>
<VersionPrefix>3.15.6</VersionPrefix> <VersionPrefix>3.14.0</VersionPrefix>
<!-- C# 7.2 is required for Span/BufferWriter/ReadOnlySequence --> <!-- C# 7.2 is required for Span/BufferWriter/ReadOnlySequence -->
<LangVersion>7.2</LangVersion> <LangVersion>7.2</LangVersion>
<Authors>Google Inc.</Authors> <Authors>Google Inc.</Authors>
@ -12,32 +12,35 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyOriginatorKeyFile>./keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>./keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageTags>Protocol;Buffers;Binary;Serialization;Format;Google;proto;proto3</PackageTags> <PackageTags>Protocol;Buffers;Binary;Serialization;Format;Google;proto;proto3</PackageTags>
<PackageReleaseNotes>C# proto3 support</PackageReleaseNotes> <PackageReleaseNotes>C# proto3 support</PackageReleaseNotes>
<PackageProjectUrl>https://github.com/protocolbuffers/protobuf</PackageProjectUrl> <PackageProjectUrl>https://github.com/protocolbuffers/protobuf</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/protocolbuffers/protobuf/blob/master/LICENSE</PackageLicenseUrl> <PackageLicenseUrl>https://github.com/protocolbuffers/protobuf/blob/master/LICENSE</PackageLicenseUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/protocolbuffers/protobuf.git</RepositoryUrl> <RepositoryUrl>https://github.com/protocolbuffers/protobuf.git</RepositoryUrl>
<DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_SYSTEM_MEMORY</DefineConstants>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<!-- Include PDB in the built .nupkg --> <!-- Include PDB in the built .nupkg -->
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder> <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<ReleaseVersion>0.7.1</ReleaseVersion> <ReleaseVersion>0.7.1</ReleaseVersion>
<AssemblyName>LC.Google.Protobuf</AssemblyName> <PackageId>LC.Google.Protobuf</PackageId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' "> <PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_FAST_STRING</DefineConstants> <DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_FAST_STRING</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net50' ">
<DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_FAST_STRING;GOOGLE_PROTOBUF_SIMD</DefineConstants>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Memory" Version="4.5.3" />
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="1.0.0" /> <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="1.0.0" />
<!-- Needed for the net45 build to work on Unix. See https://github.com/dotnet/designs/pull/33 --> <!-- Needed for the net45 build to work on Unix. See https://github.com/dotnet/designs/pull/33 -->
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.0" /> <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.0" />
<PackageReference Include="System.Memory" Version="4.5.4" /> </ItemGroup>
<!-- Needed for netcoreapp2.1 to work correctly. .NET is not able to load the assembly without this -->
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.2" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -32,11 +32,9 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Security; using System.Security;
using LC.Google.Protobuf.Collections;
namespace LC.Google.Protobuf namespace LC.Google.Protobuf
{ {
@ -46,8 +44,6 @@ namespace LC.Google.Protobuf
[SecuritySafeCritical] [SecuritySafeCritical]
internal static class ParsingPrimitivesMessages internal static class ParsingPrimitivesMessages
{ {
private static readonly byte[] ZeroLengthMessageStreamData = new byte[] { 0 };
public static void SkipLastField(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state) public static void SkipLastField(ref ReadOnlySpan<byte> buffer, ref ParserInternalState state)
{ {
if (state.lastTag == 0) if (state.lastTag == 0)
@ -138,65 +134,6 @@ namespace LC.Google.Protobuf
SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit);
} }
public static KeyValuePair<TKey, TValue> ReadMapEntry<TKey, TValue>(ref ParseContext ctx, MapField<TKey, TValue>.Codec codec)
{
int length = ParsingPrimitives.ParseLength(ref ctx.buffer, ref ctx.state);
if (ctx.state.recursionDepth >= ctx.state.recursionLimit)
{
throw InvalidProtocolBufferException.RecursionLimitExceeded();
}
int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length);
++ctx.state.recursionDepth;
TKey key = codec.KeyCodec.DefaultValue;
TValue value = codec.ValueCodec.DefaultValue;
uint tag;
while ((tag = ctx.ReadTag()) != 0)
{
if (tag == codec.KeyCodec.Tag)
{
key = codec.KeyCodec.Read(ref ctx);
}
else if (tag == codec.ValueCodec.Tag)
{
value = codec.ValueCodec.Read(ref ctx);
}
else
{
SkipLastField(ref ctx.buffer, ref ctx.state);
}
}
// Corner case: a map entry with a key but no value, where the value type is a message.
// Read it as if we'd seen input with no data (i.e. create a "default" message).
if (value == null)
{
if (ctx.state.CodedInputStream != null)
{
// the decoded message might not support parsing from ParseContext, so
// we need to allow fallback to the legacy MergeFrom(CodedInputStream) parsing.
value = codec.ValueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData));
}
else
{
ParseContext.Initialize(new ReadOnlySequence<byte>(ZeroLengthMessageStreamData), out ParseContext zeroLengthCtx);
value = codec.ValueCodec.Read(ref zeroLengthCtx);
}
}
CheckReadEndOfStreamTag(ref ctx.state);
// Check that we've read exactly as much data as expected.
if (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state))
{
throw InvalidProtocolBufferException.TruncatedMessage();
}
--ctx.state.recursionDepth;
SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit);
return new KeyValuePair<TKey, TValue>(key, value);
}
public static void ReadGroup(ref ParseContext ctx, IMessage message) public static void ReadGroup(ref ParseContext ctx, IMessage message)
{ {
if (ctx.state.recursionDepth >= ctx.state.recursionLimit) if (ctx.state.recursionDepth >= ctx.state.recursionLimit)

View File

@ -107,58 +107,57 @@ namespace LC.Google.Protobuf.Reflection {
"eV9wYWNrYWdlGC0gASgJEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo", "eV9wYWNrYWdlGC0gASgJEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo",
"CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIjoKDE9w", "CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIjoKDE9w",
"dGltaXplTW9kZRIJCgVTUEVFRBABEg0KCUNPREVfU0laRRACEhAKDExJVEVf", "dGltaXplTW9kZRIJCgVTUEVFRBABEg0KCUNPREVfU0laRRACEhAKDExJVEVf",
"UlVOVElNRRADKgkI6AcQgICAgAJKBAgmECcihAIKDk1lc3NhZ2VPcHRpb25z", "UlVOVElNRRADKgkI6AcQgICAgAJKBAgmECci8gEKDk1lc3NhZ2VPcHRpb25z",
"EiYKF21lc3NhZ2Vfc2V0X3dpcmVfZm9ybWF0GAEgASgIOgVmYWxzZRIuCh9u", "EiYKF21lc3NhZ2Vfc2V0X3dpcmVfZm9ybWF0GAEgASgIOgVmYWxzZRIuCh9u",
"b19zdGFuZGFyZF9kZXNjcmlwdG9yX2FjY2Vzc29yGAIgASgIOgVmYWxzZRIZ", "b19zdGFuZGFyZF9kZXNjcmlwdG9yX2FjY2Vzc29yGAIgASgIOgVmYWxzZRIZ",
"CgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRIRCgltYXBfZW50cnkYByABKAgS", "CgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRIRCgltYXBfZW50cnkYByABKAgS",
"QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv", "QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv",
"YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAQQBUoECAUQ", "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAgQCUoECAkQ",
"BkoECAYQB0oECAgQCUoECAkQCiKeAwoMRmllbGRPcHRpb25zEjoKBWN0eXBl", "CiKeAwoMRmllbGRPcHRpb25zEjoKBWN0eXBlGAEgASgOMiMuZ29vZ2xlLnBy",
"GAEgASgOMiMuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToG", "b3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToGU1RSSU5HEg4KBnBhY2tlZBgC",
"U1RSSU5HEg4KBnBhY2tlZBgCIAEoCBI/CgZqc3R5cGUYBiABKA4yJC5nb29n", "IAEoCBI/CgZqc3R5cGUYBiABKA4yJC5nb29nbGUucHJvdG9idWYuRmllbGRP",
"bGUucHJvdG9idWYuRmllbGRPcHRpb25zLkpTVHlwZToJSlNfTk9STUFMEhMK", "cHRpb25zLkpTVHlwZToJSlNfTk9STUFMEhMKBGxhenkYBSABKAg6BWZhbHNl",
"BGxhenkYBSABKAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNl", "EhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEhMKBHdlYWsYCiABKAg6BWZh",
"EhMKBHdlYWsYCiABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9u", "bHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5w",
"GOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9u", "cm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIi8KBUNUeXBlEgoKBlNUUklO",
"Ii8KBUNUeXBlEgoKBlNUUklORxAAEggKBENPUkQQARIQCgxTVFJJTkdfUElF", "RxAAEggKBENPUkQQARIQCgxTVFJJTkdfUElFQ0UQAiI1CgZKU1R5cGUSDQoJ",
"Q0UQAiI1CgZKU1R5cGUSDQoJSlNfTk9STUFMEAASDQoJSlNfU1RSSU5HEAES", "SlNfTk9STUFMEAASDQoJSlNfU1RSSU5HEAESDQoJSlNfTlVNQkVSEAIqCQjo",
"DQoJSlNfTlVNQkVSEAIqCQjoBxCAgICAAkoECAQQBSJeCgxPbmVvZk9wdGlv", "BxCAgICAAkoECAQQBSJeCgxPbmVvZk9wdGlvbnMSQwoUdW5pbnRlcnByZXRl",
"bnMSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnBy", "ZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0",
"b3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiKTAQoLRW51", "ZWRPcHRpb24qCQjoBxCAgICAAiKTAQoLRW51bU9wdGlvbnMSEwoLYWxsb3df",
"bU9wdGlvbnMSEwoLYWxsb3dfYWxpYXMYAiABKAgSGQoKZGVwcmVjYXRlZBgD", "YWxpYXMYAiABKAgSGQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USQwoUdW5p",
"IAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQu", "bnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVu",
"Z29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICA", "aW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAUQBiJ9ChBFbnVtVmFs",
"AkoECAUQBiJ9ChBFbnVtVmFsdWVPcHRpb25zEhkKCmRlcHJlY2F0ZWQYASAB", "dWVPcHRpb25zEhkKCmRlcHJlY2F0ZWQYASABKAg6BWZhbHNlEkMKFHVuaW50",
"KAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdv", "ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu",
"b2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIi", "dGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIiewoOU2VydmljZU9wdGlvbnMS",
"ewoOU2VydmljZU9wdGlvbnMSGQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2US", "GQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9v",
"QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv", "cHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRP",
"YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiKtAgoNTWV0aG9k", "cHRpb24qCQjoBxCAgICAAiKtAgoNTWV0aG9kT3B0aW9ucxIZCgpkZXByZWNh",
"T3B0aW9ucxIZCgpkZXByZWNhdGVkGCEgASgIOgVmYWxzZRJfChFpZGVtcG90", "dGVkGCEgASgIOgVmYWxzZRJfChFpZGVtcG90ZW5jeV9sZXZlbBgiIAEoDjIv",
"ZW5jeV9sZXZlbBgiIAEoDjIvLmdvb2dsZS5wcm90b2J1Zi5NZXRob2RPcHRp", "Lmdvb2dsZS5wcm90b2J1Zi5NZXRob2RPcHRpb25zLklkZW1wb3RlbmN5TGV2",
"b25zLklkZW1wb3RlbmN5TGV2ZWw6E0lERU1QT1RFTkNZX1VOS05PV04SQwoU", "ZWw6E0lERU1QT1RFTkNZX1VOS05PV04SQwoUdW5pbnRlcnByZXRlZF9vcHRp",
"dW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVm", "b24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRp",
"LlVuaW50ZXJwcmV0ZWRPcHRpb24iUAoQSWRlbXBvdGVuY3lMZXZlbBIXChNJ", "b24iUAoQSWRlbXBvdGVuY3lMZXZlbBIXChNJREVNUE9URU5DWV9VTktOT1dO",
"REVNUE9URU5DWV9VTktOT1dOEAASEwoPTk9fU0lERV9FRkZFQ1RTEAESDgoK", "EAASEwoPTk9fU0lERV9FRkZFQ1RTEAESDgoKSURFTVBPVEVOVBACKgkI6AcQ",
"SURFTVBPVEVOVBACKgkI6AcQgICAgAIingIKE1VuaW50ZXJwcmV0ZWRPcHRp", "gICAgAIingIKE1VuaW50ZXJwcmV0ZWRPcHRpb24SOwoEbmFtZRgCIAMoCzIt",
"b24SOwoEbmFtZRgCIAMoCzItLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJl", "Lmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uLk5hbWVQYXJ0",
"dGVkT3B0aW9uLk5hbWVQYXJ0EhgKEGlkZW50aWZpZXJfdmFsdWUYAyABKAkS", "EhgKEGlkZW50aWZpZXJfdmFsdWUYAyABKAkSGgoScG9zaXRpdmVfaW50X3Zh",
"GgoScG9zaXRpdmVfaW50X3ZhbHVlGAQgASgEEhoKEm5lZ2F0aXZlX2ludF92", "bHVlGAQgASgEEhoKEm5lZ2F0aXZlX2ludF92YWx1ZRgFIAEoAxIUCgxkb3Vi",
"YWx1ZRgFIAEoAxIUCgxkb3VibGVfdmFsdWUYBiABKAESFAoMc3RyaW5nX3Zh", "bGVfdmFsdWUYBiABKAESFAoMc3RyaW5nX3ZhbHVlGAcgASgMEhcKD2FnZ3Jl",
"bHVlGAcgASgMEhcKD2FnZ3JlZ2F0ZV92YWx1ZRgIIAEoCRozCghOYW1lUGFy", "Z2F0ZV92YWx1ZRgIIAEoCRozCghOYW1lUGFydBIRCgluYW1lX3BhcnQYASAC",
"dBIRCgluYW1lX3BhcnQYASACKAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigIItUB", "KAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigIItUBCg5Tb3VyY2VDb2RlSW5mbxI6",
"Cg5Tb3VyY2VDb2RlSW5mbxI6Cghsb2NhdGlvbhgBIAMoCzIoLmdvb2dsZS5w", "Cghsb2NhdGlvbhgBIAMoCzIoLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2Rl",
"cm90b2J1Zi5Tb3VyY2VDb2RlSW5mby5Mb2NhdGlvbhqGAQoITG9jYXRpb24S", "SW5mby5Mb2NhdGlvbhqGAQoITG9jYXRpb24SEAoEcGF0aBgBIAMoBUICEAES",
"EAoEcGF0aBgBIAMoBUICEAESEAoEc3BhbhgCIAMoBUICEAESGAoQbGVhZGlu", "EAoEc3BhbhgCIAMoBUICEAESGAoQbGVhZGluZ19jb21tZW50cxgDIAEoCRIZ",
"Z19jb21tZW50cxgDIAEoCRIZChF0cmFpbGluZ19jb21tZW50cxgEIAEoCRIh", "ChF0cmFpbGluZ19jb21tZW50cxgEIAEoCRIhChlsZWFkaW5nX2RldGFjaGVk",
"ChlsZWFkaW5nX2RldGFjaGVkX2NvbW1lbnRzGAYgAygJIqcBChFHZW5lcmF0", "X2NvbW1lbnRzGAYgAygJIqcBChFHZW5lcmF0ZWRDb2RlSW5mbxJBCgphbm5v",
"ZWRDb2RlSW5mbxJBCgphbm5vdGF0aW9uGAEgAygLMi0uZ29vZ2xlLnByb3Rv", "dGF0aW9uGAEgAygLMi0uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZENvZGVJ",
"YnVmLkdlbmVyYXRlZENvZGVJbmZvLkFubm90YXRpb24aTwoKQW5ub3RhdGlv", "bmZvLkFubm90YXRpb24aTwoKQW5ub3RhdGlvbhIQCgRwYXRoGAEgAygFQgIQ",
"bhIQCgRwYXRoGAEgAygFQgIQARITCgtzb3VyY2VfZmlsZRgCIAEoCRINCgVi", "ARITCgtzb3VyY2VfZmlsZRgCIAEoCRINCgViZWdpbhgDIAEoBRILCgNlbmQY",
"ZWdpbhgDIAEoBRILCgNlbmQYBCABKAVCfgoTY29tLmdvb2dsZS5wcm90b2J1", "BCABKAVCfgoTY29tLmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRvclByb3Rv",
"ZkIQRGVzY3JpcHRvclByb3Rvc0gBWi1nb29nbGUuZ29sYW5nLm9yZy9wcm90", "c0gBWi1nb29nbGUuZ29sYW5nLm9yZy9wcm90b2J1Zi90eXBlcy9kZXNjcmlw",
"b2J1Zi90eXBlcy9kZXNjcmlwdG9ycGL4AQGiAgNHUEKqAhpHb29nbGUuUHJv", "dG9ycGL4AQGiAgNHUEKqAhpHb29nbGUuUHJvdG9idWYuUmVmbGVjdGlvbg=="));
"dG9idWYuUmVmbGVjdGlvbg=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { }, new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {

View File

@ -481,21 +481,18 @@ namespace LC.Google.Protobuf.Reflection
/// dependencies must come before the descriptor which depends on them. (If A depends on B, and B /// dependencies must come before the descriptor which depends on them. (If A depends on B, and B
/// depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible /// depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible
/// with the order in which protoc provides descriptors to plugins.</param> /// with the order in which protoc provides descriptors to plugins.</param>
/// <param name="registry">The extension registry to use when parsing, or null if no extensions are required.</param>
/// <returns>The file descriptors corresponding to <paramref name="descriptorData"/>.</returns> /// <returns>The file descriptors corresponding to <paramref name="descriptorData"/>.</returns>
public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<ByteString> descriptorData, ExtensionRegistry registry) public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<ByteString> descriptorData)
{ {
ProtoPreconditions.CheckNotNull(descriptorData, nameof(descriptorData)); ProtoPreconditions.CheckNotNull(descriptorData, nameof(descriptorData));
var parser = FileDescriptorProto.Parser.WithExtensionRegistry(registry);
// TODO: See if we can build a single DescriptorPool instead of building lots of them. // TODO: See if we can build a single DescriptorPool instead of building lots of them.
// This will all behave correctly, but it's less efficient than we'd like. // This will all behave correctly, but it's less efficient than we'd like.
var descriptors = new List<FileDescriptor>(); var descriptors = new List<FileDescriptor>();
var descriptorsByName = new Dictionary<string, FileDescriptor>(); var descriptorsByName = new Dictionary<string, FileDescriptor>();
foreach (var data in descriptorData) foreach (var data in descriptorData)
{ {
var proto = parser.ParseFrom(data); var proto = FileDescriptorProto.Parser.ParseFrom(data);
var dependencies = new List<FileDescriptor>(); var dependencies = new List<FileDescriptor>();
foreach (var dependencyName in proto.Dependency) foreach (var dependencyName in proto.Dependency)
{ {
@ -521,18 +518,6 @@ namespace LC.Google.Protobuf.Reflection
return new ReadOnlyCollection<FileDescriptor>(descriptors); return new ReadOnlyCollection<FileDescriptor>(descriptors);
} }
/// <summary>
/// Converts the given descriptor binary data into FileDescriptor objects.
/// Note: reflection using the returned FileDescriptors is not currently supported.
/// </summary>
/// <param name="descriptorData">The binary file descriptor proto data. Must not be null, and any
/// dependencies must come before the descriptor which depends on them. (If A depends on B, and B
/// depends on C, then the descriptors must be presented in the order C, B, A.) This is compatible
/// with the order in which protoc provides descriptors to plugins.</param>
/// <returns>The file descriptors corresponding to <paramref name="descriptorData"/>.</returns>
public static IReadOnlyList<FileDescriptor> BuildFromByteStrings(IEnumerable<ByteString> descriptorData) =>
BuildFromByteStrings(descriptorData, null);
/// <summary> /// <summary>
/// Returns a <see cref="System.String" /> that represents this instance. /// Returns a <see cref="System.String" /> that represents this instance.
/// </summary> /// </summary>

View File

@ -1,81 +0,0 @@
#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Security;
namespace LC.Google.Protobuf
{
/// <summary>
/// Provides a number of unsafe byte operations to be used by advanced applications with high performance
/// requirements. These methods are referred to as "unsafe" due to the fact that they potentially expose
/// the backing buffer of a <see cref="ByteString"/> to the application.
/// </summary>
/// <remarks>
/// <para>
/// The methods in this class should only be called if it is guaranteed that the buffer backing the
/// <see cref="ByteString"/> will never change! Mutation of a <see cref="ByteString"/> can lead to unexpected
/// and undesirable consequences in your application, and will likely be difficult to debug. Proceed with caution!
/// </para>
/// <para>
/// This can have a number of significant side affects that have spooky-action-at-a-distance-like behavior. In
/// particular, if the bytes value changes out from under a Protocol Buffer:
/// </para>
/// <list type="bullet">
/// <item>
/// <description>serialization may throw</description>
/// </item>
/// <item>
/// <description>serialization may succeed but the wrong bytes may be written out</description>
/// </item>
/// <item>
/// <description>objects that are normally immutable (such as ByteString) are no longer immutable</description>
/// </item>
/// <item>
/// <description>hashCode may be incorrect</description>
/// </item>
/// </list>
/// </remarks>
[SecuritySafeCritical]
public static class UnsafeByteOperations
{
/// <summary>
/// Constructs a new <see cref="ByteString" /> from the given bytes. The bytes are not copied,
/// and must not be modified while the <see cref="ByteString" /> is in use.
/// This API is experimental and subject to change.
/// </summary>
public static ByteString UnsafeWrap(ReadOnlyMemory<byte> bytes)
{
return ByteString.AttachBytes(bytes);
}
}
}

View File

@ -32,14 +32,8 @@
using System; using System;
using System.Buffers.Binary; using System.Buffers.Binary;
using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
#if GOOGLE_PROTOBUF_SIMD
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.Arm;
using System.Runtime.Intrinsics.X86;
#endif
using System.Security; using System.Security;
using System.Text; using System.Text;
@ -51,11 +45,8 @@ namespace LC.Google.Protobuf
[SecuritySafeCritical] [SecuritySafeCritical]
internal static class WritingPrimitives internal static class WritingPrimitives
{ {
#if NET5_0 // "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.)
internal static Encoding Utf8Encoding => Encoding.UTF8; // allows JIT to devirtualize internal static readonly Encoding Utf8Encoding = Encoding.UTF8;
#else
internal static readonly Encoding Utf8Encoding = Encoding.UTF8; // "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.)
#endif
#region Writing of values (not including tags) #region Writing of values (not including tags)
@ -172,34 +163,39 @@ namespace LC.Google.Protobuf
/// </summary> /// </summary>
public static void WriteString(ref Span<byte> buffer, ref WriterInternalState state, string value) public static void WriteString(ref Span<byte> buffer, ref WriterInternalState state, string value)
{ {
const int MaxBytesPerChar = 3;
const int MaxSmallStringLength = 128 / MaxBytesPerChar;
// The string is small enough that the length will always be a 1 byte varint.
// Also there is enough space to write length + bytes to buffer.
// Write string directly to the buffer, and then write length.
// This saves calling GetByteCount on the string. We get the string length from GetBytes.
if (value.Length <= MaxSmallStringLength && buffer.Length - state.position - 1 >= value.Length * MaxBytesPerChar)
{
int indexOfLengthDelimiter = state.position++;
buffer[indexOfLengthDelimiter] = (byte)WriteStringToBuffer(buffer, ref state, value);
return;
}
int length = Utf8Encoding.GetByteCount(value);
WriteLength(ref buffer, ref state, length);
// Optimise the case where we have enough space to write // Optimise the case where we have enough space to write
// the string directly to the buffer, which should be common. // the string directly to the buffer, which should be common.
int length = Utf8Encoding.GetByteCount(value);
WriteLength(ref buffer, ref state, length);
if (buffer.Length - state.position >= length) if (buffer.Length - state.position >= length)
{ {
if (length == value.Length) // Must be all ASCII... if (length == value.Length) // Must be all ASCII...
{ {
WriteAsciiStringToBuffer(buffer, ref state, value, length); for (int i = 0; i < length; i++)
{
buffer[state.position + i] = (byte)value[i];
}
state.position += length;
} }
else else
{ {
WriteStringToBuffer(buffer, ref state, value); #if NETSTANDARD1_1
// slowpath when Encoding.GetBytes(Char*, Int32, Byte*, Int32) is not available
byte[] bytes = Utf8Encoding.GetBytes(value);
WriteRawBytes(ref buffer, ref state, bytes);
#else
ReadOnlySpan<char> source = value.AsSpan();
int bytesUsed;
unsafe
{
fixed (char* sourceChars = &MemoryMarshal.GetReference(source))
fixed (byte* destinationBytes = &MemoryMarshal.GetReference(buffer.Slice(state.position)))
{
bytesUsed = Utf8Encoding.GetBytes(sourceChars, source.Length, destinationBytes, buffer.Length);
}
}
state.position += bytesUsed;
#endif
} }
} }
else else
@ -213,131 +209,6 @@ namespace LC.Google.Protobuf
} }
} }
// Calling this method with non-ASCII content will break.
// Content must be verified to be all ASCII before using this method.
private static void WriteAsciiStringToBuffer(Span<byte> buffer, ref WriterInternalState state, string value, int length)
{
ref char sourceChars = ref MemoryMarshal.GetReference(value.AsSpan());
ref byte destinationBytes = ref MemoryMarshal.GetReference(buffer.Slice(state.position));
int currentIndex = 0;
// If 64bit, process 4 chars at a time.
// The logic inside this check will be elided by JIT in 32bit programs.
if (IntPtr.Size == 8)
{
// Need at least 4 chars available to use this optimization.
if (length >= 4)
{
ref byte sourceBytes = ref Unsafe.As<char, byte>(ref sourceChars);
// Process 4 chars at a time until there are less than 4 remaining.
// We already know all characters are ASCII so there is no need to validate the source.
int lastIndexWhereCanReadFourChars = value.Length - 4;
do
{
NarrowFourUtf16CharsToAsciiAndWriteToBuffer(
ref Unsafe.AddByteOffset(ref destinationBytes, (IntPtr)currentIndex),
Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref sourceBytes, (IntPtr)(currentIndex * 2))));
} while ((currentIndex += 4) <= lastIndexWhereCanReadFourChars);
}
}
// Process any remaining, 1 char at a time.
// Avoid bounds checking with ref + Unsafe
for (; currentIndex < length; currentIndex++)
{
Unsafe.AddByteOffset(ref destinationBytes, (IntPtr)currentIndex) = (byte)Unsafe.AddByteOffset(ref sourceChars, (IntPtr)(currentIndex * 2));
}
state.position += length;
}
// Copied with permission from https://github.com/dotnet/runtime/blob/1cdafd27e4afd2c916af5df949c13f8b373c4335/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.cs#L1119-L1171
//
/// <summary>
/// Given a QWORD which represents a buffer of 4 ASCII chars in machine-endian order,
/// narrows each WORD to a BYTE, then writes the 4-byte result to the output buffer
/// also in machine-endian order.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void NarrowFourUtf16CharsToAsciiAndWriteToBuffer(ref byte outputBuffer, ulong value)
{
#if GOOGLE_PROTOBUF_SIMD
if (Sse2.X64.IsSupported)
{
// Narrows a vector of words [ w0 w1 w2 w3 ] to a vector of bytes
// [ b0 b1 b2 b3 b0 b1 b2 b3 ], then writes 4 bytes (32 bits) to the destination.
Vector128<short> vecWide = Sse2.X64.ConvertScalarToVector128UInt64(value).AsInt16();
Vector128<uint> vecNarrow = Sse2.PackUnsignedSaturate(vecWide, vecWide).AsUInt32();
Unsafe.WriteUnaligned<uint>(ref outputBuffer, Sse2.ConvertToUInt32(vecNarrow));
}
else if (AdvSimd.IsSupported)
{
// Narrows a vector of words [ w0 w1 w2 w3 ] to a vector of bytes
// [ b0 b1 b2 b3 * * * * ], then writes 4 bytes (32 bits) to the destination.
Vector128<short> vecWide = Vector128.CreateScalarUnsafe(value).AsInt16();
Vector64<byte> lower = AdvSimd.ExtractNarrowingSaturateUnsignedLower(vecWide);
Unsafe.WriteUnaligned<uint>(ref outputBuffer, lower.AsUInt32().ToScalar());
}
else
#endif
{
// Fallback to non-SIMD approach when SIMD is not available.
// This could happen either because the APIs are not available, or hardware doesn't support it.
// Processing 4 chars at a time in this fallback is still faster than casting one char at a time.
if (BitConverter.IsLittleEndian)
{
outputBuffer = (byte)value;
value >>= 16;
Unsafe.Add(ref outputBuffer, 1) = (byte)value;
value >>= 16;
Unsafe.Add(ref outputBuffer, 2) = (byte)value;
value >>= 16;
Unsafe.Add(ref outputBuffer, 3) = (byte)value;
}
else
{
Unsafe.Add(ref outputBuffer, 3) = (byte)value;
value >>= 16;
Unsafe.Add(ref outputBuffer, 2) = (byte)value;
value >>= 16;
Unsafe.Add(ref outputBuffer, 1) = (byte)value;
value >>= 16;
outputBuffer = (byte)value;
}
}
}
private static int WriteStringToBuffer(Span<byte> buffer, ref WriterInternalState state, string value)
{
#if NETSTANDARD1_1
// slowpath when Encoding.GetBytes(Char*, Int32, Byte*, Int32) is not available
byte[] bytes = Utf8Encoding.GetBytes(value);
WriteRawBytes(ref buffer, ref state, bytes);
return bytes.Length;
#else
ReadOnlySpan<char> source = value.AsSpan();
int bytesUsed;
unsafe
{
fixed (char* sourceChars = &MemoryMarshal.GetReference(source))
fixed (byte* destinationBytes = &MemoryMarshal.GetReference(buffer))
{
bytesUsed = Utf8Encoding.GetBytes(
sourceChars,
source.Length,
destinationBytes + state.position,
buffer.Length - state.position);
}
}
state.position += bytesUsed;
return bytesUsed;
#endif
}
/// <summary> /// <summary>
/// Write a byte string, without a tag, to the stream. /// Write a byte string, without a tag, to the stream.
/// The data is length-prefixed. /// The data is length-prefixed.

View File

@ -25,8 +25,6 @@
using System; using System;
#nullable disable
namespace LC.Newtonsoft.Json.Bson namespace LC.Newtonsoft.Json.Bson
{ {
internal enum BsonBinaryType : byte internal enum BsonBinaryType : byte

View File

@ -29,8 +29,6 @@ using System.IO;
using System.Text; using System.Text;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
#nullable disable
namespace LC.Newtonsoft.Json.Bson namespace LC.Newtonsoft.Json.Bson
{ {
internal class BsonBinaryWriter internal class BsonBinaryWriter

View File

@ -26,8 +26,6 @@
using System; using System;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
#nullable disable
namespace LC.Newtonsoft.Json.Bson namespace LC.Newtonsoft.Json.Bson
{ {
/// <summary> /// <summary>

View File

@ -32,8 +32,6 @@ using LC.Newtonsoft.Json.Serialization;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using LC.Newtonsoft.Json.Linq; using LC.Newtonsoft.Json.Linq;
#nullable disable
namespace LC.Newtonsoft.Json.Bson namespace LC.Newtonsoft.Json.Bson
{ {
/// <summary> /// <summary>

View File

@ -26,8 +26,6 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
#nullable disable
namespace LC.Newtonsoft.Json.Bson namespace LC.Newtonsoft.Json.Bson
{ {
internal abstract class BsonToken internal abstract class BsonToken

View File

@ -23,8 +23,6 @@
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
#endregion #endregion
#nullable disable
namespace LC.Newtonsoft.Json.Bson namespace LC.Newtonsoft.Json.Bson
{ {
internal enum BsonType : sbyte internal enum BsonType : sbyte

View File

@ -35,8 +35,6 @@ using LC.Newtonsoft.Json.Utilities;
using LC.Newtonsoft.Json.Linq; using LC.Newtonsoft.Json.Linq;
using System.Globalization; using System.Globalization;
#nullable disable
namespace LC.Newtonsoft.Json.Bson namespace LC.Newtonsoft.Json.Bson
{ {
/// <summary> /// <summary>

View File

@ -28,7 +28,6 @@ using System;
using System.Globalization; using System.Globalization;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
#if HAVE_ADO_NET #if HAVE_ADO_NET
using System.Data.SqlTypes; using System.Data.SqlTypes;
#endif #endif
@ -43,7 +42,7 @@ namespace LC.Newtonsoft.Json.Converters
#if HAVE_LINQ #if HAVE_LINQ
private const string BinaryTypeName = "System.Data.Linq.Binary"; private const string BinaryTypeName = "System.Data.Linq.Binary";
private const string BinaryToArrayName = "ToArray"; private const string BinaryToArrayName = "ToArray";
private static ReflectionObject? _reflectionObject; private static ReflectionObject _reflectionObject;
#endif #endif
/// <summary> /// <summary>
@ -52,7 +51,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (value == null) if (value == null)
{ {
@ -71,9 +70,7 @@ namespace LC.Newtonsoft.Json.Converters
if (value.GetType().FullName == BinaryTypeName) if (value.GetType().FullName == BinaryTypeName)
{ {
EnsureReflectionObject(value.GetType()); EnsureReflectionObject(value.GetType());
MiscellaneousUtils.Assert(_reflectionObject != null); return (byte[])_reflectionObject.GetValue(value, BinaryToArrayName);
return (byte[])_reflectionObject.GetValue(value, BinaryToArrayName)!;
} }
#endif #endif
#if HAVE_ADO_NET #if HAVE_ADO_NET
@ -104,7 +101,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
if (reader.TokenType == JsonToken.Null) if (reader.TokenType == JsonToken.Null)
{ {
@ -126,7 +123,7 @@ namespace LC.Newtonsoft.Json.Converters
{ {
// current token is already at base64 string // current token is already at base64 string
// unable to call ReadAsBytes so do it the old fashion way // unable to call ReadAsBytes so do it the old fashion way
string encodedData = reader.Value!.ToString(); string encodedData = reader.Value.ToString();
data = Convert.FromBase64String(encodedData); data = Convert.FromBase64String(encodedData);
} }
else else
@ -142,9 +139,8 @@ namespace LC.Newtonsoft.Json.Converters
if (t.FullName == BinaryTypeName) if (t.FullName == BinaryTypeName)
{ {
EnsureReflectionObject(t); EnsureReflectionObject(t);
MiscellaneousUtils.Assert(_reflectionObject != null);
return _reflectionObject.Creator!(data); return _reflectionObject.Creator(data);
} }
#endif #endif

View File

@ -28,8 +28,6 @@ using LC.Newtonsoft.Json.Bson;
using System.Globalization; using System.Globalization;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
#nullable disable
namespace LC.Newtonsoft.Json.Converters namespace LC.Newtonsoft.Json.Converters
{ {
/// <summary> /// <summary>

View File

@ -41,7 +41,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
throw new NotSupportedException("CustomCreationConverter should only be used while deserializing."); throw new NotSupportedException("CustomCreationConverter should only be used while deserializing.");
} }
@ -54,7 +54,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
if (reader.TokenType == JsonToken.Null) if (reader.TokenType == JsonToken.Null)
{ {

View File

@ -41,7 +41,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (value == null) if (value == null)
{ {
@ -50,7 +50,7 @@ namespace LC.Newtonsoft.Json.Converters
} }
DataSet dataSet = (DataSet)value; DataSet dataSet = (DataSet)value;
DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
DataTableConverter converter = new DataTableConverter(); DataTableConverter converter = new DataTableConverter();
@ -74,7 +74,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
if (reader.TokenType == JsonToken.Null) if (reader.TokenType == JsonToken.Null)
{ {
@ -92,10 +92,10 @@ namespace LC.Newtonsoft.Json.Converters
while (reader.TokenType == JsonToken.PropertyName) while (reader.TokenType == JsonToken.PropertyName)
{ {
DataTable dt = ds.Tables[(string)reader.Value!]; DataTable dt = ds.Tables[(string)reader.Value];
bool exists = (dt != null); bool exists = (dt != null);
dt = (DataTable)converter.ReadJson(reader, typeof(DataTable), dt, serializer)!; dt = (DataTable)converter.ReadJson(reader, typeof(DataTable), dt, serializer);
if (!exists) if (!exists)
{ {

View File

@ -45,7 +45,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (value == null) if (value == null)
{ {
@ -54,7 +54,7 @@ namespace LC.Newtonsoft.Json.Converters
} }
DataTable table = (DataTable)value; DataTable table = (DataTable)value;
DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
writer.WriteStartArray(); writer.WriteStartArray();
@ -87,7 +87,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
if (reader.TokenType == JsonToken.Null) if (reader.TokenType == JsonToken.Null)
{ {
@ -106,7 +106,7 @@ namespace LC.Newtonsoft.Json.Converters
// populate the name from the property name // populate the name from the property name
if (reader.TokenType == JsonToken.PropertyName) if (reader.TokenType == JsonToken.PropertyName)
{ {
dt.TableName = (string)reader.Value!; dt.TableName = (string)reader.Value;
reader.ReadAndAssert(); reader.ReadAndAssert();
@ -140,7 +140,7 @@ namespace LC.Newtonsoft.Json.Converters
while (reader.TokenType == JsonToken.PropertyName) while (reader.TokenType == JsonToken.PropertyName)
{ {
string columnName = (string)reader.Value!; string columnName = (string)reader.Value;
reader.ReadAndAssert(); reader.ReadAndAssert();
@ -177,7 +177,7 @@ namespace LC.Newtonsoft.Json.Converters
reader.ReadAndAssert(); reader.ReadAndAssert();
} }
List<object?> o = new List<object?>(); List<object> o = new List<object>();
while (reader.TokenType != JsonToken.EndArray) while (reader.TokenType != JsonToken.EndArray)
{ {
@ -218,7 +218,7 @@ namespace LC.Newtonsoft.Json.Converters
case JsonToken.String: case JsonToken.String:
case JsonToken.Date: case JsonToken.Date:
case JsonToken.Bytes: case JsonToken.Bytes:
return reader.ValueType!; return reader.ValueType;
case JsonToken.Null: case JsonToken.Null:
case JsonToken.Undefined: case JsonToken.Undefined:
case JsonToken.EndArray: case JsonToken.EndArray:

View File

@ -48,32 +48,17 @@ namespace LC.Newtonsoft.Json.Converters
#region UnionDefinition #region UnionDefinition
internal class Union internal class Union
{ {
public readonly FSharpFunction TagReader; public List<UnionCase> Cases;
public readonly List<UnionCase> Cases; public FSharpFunction TagReader { get; set; }
public Union(FSharpFunction tagReader, List<UnionCase> cases)
{
TagReader = tagReader;
Cases = cases;
}
} }
internal class UnionCase internal class UnionCase
{ {
public readonly int Tag; public int Tag;
public readonly string Name; public string Name;
public readonly PropertyInfo[] Fields; public PropertyInfo[] Fields;
public readonly FSharpFunction FieldReader; public FSharpFunction FieldReader;
public readonly FSharpFunction Constructor; public FSharpFunction Constructor;
public UnionCase(int tag, string name, PropertyInfo[] fields, FSharpFunction fieldReader, FSharpFunction constructor)
{
Tag = tag;
Name = name;
Fields = fields;
FieldReader = fieldReader;
Constructor = constructor;
}
} }
#endregion #endregion
@ -89,28 +74,31 @@ namespace LC.Newtonsoft.Json.Converters
// need to get declaring type to avoid duplicate Unions in cache // need to get declaring type to avoid duplicate Unions in cache
// hacky but I can't find an API to get the declaring type without GetUnionCases // hacky but I can't find an API to get the declaring type without GetUnionCases
object[] cases = (object[])FSharpUtils.Instance.GetUnionCases(null, t, null)!; object[] cases = (object[])FSharpUtils.GetUnionCases(null, t, null);
object caseInfo = cases.First(); object caseInfo = cases.First();
Type unionType = (Type)FSharpUtils.Instance.GetUnionCaseInfoDeclaringType(caseInfo)!; Type unionType = (Type)FSharpUtils.GetUnionCaseInfoDeclaringType(caseInfo);
return unionType; return unionType;
} }
private static Union CreateUnion(Type t) private static Union CreateUnion(Type t)
{ {
Union u = new Union((FSharpFunction)FSharpUtils.Instance.PreComputeUnionTagReader(null, t, null), new List<UnionCase>()); Union u = new Union();
object[] cases = (object[])FSharpUtils.Instance.GetUnionCases(null, t, null)!; u.TagReader = (FSharpFunction)FSharpUtils.PreComputeUnionTagReader(null, t, null);
u.Cases = new List<UnionCase>();
object[] cases = (object[])FSharpUtils.GetUnionCases(null, t, null);
foreach (object unionCaseInfo in cases) foreach (object unionCaseInfo in cases)
{ {
UnionCase unionCase = new UnionCase( UnionCase unionCase = new UnionCase();
(int)FSharpUtils.Instance.GetUnionCaseInfoTag(unionCaseInfo), unionCase.Tag = (int)FSharpUtils.GetUnionCaseInfoTag(unionCaseInfo);
(string)FSharpUtils.Instance.GetUnionCaseInfoName(unionCaseInfo), unionCase.Name = (string)FSharpUtils.GetUnionCaseInfoName(unionCaseInfo);
(PropertyInfo[])FSharpUtils.Instance.GetUnionCaseInfoFields(unionCaseInfo)!, unionCase.Fields = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(unionCaseInfo);
(FSharpFunction)FSharpUtils.Instance.PreComputeUnionReader(null, unionCaseInfo, null), unionCase.FieldReader = (FSharpFunction)FSharpUtils.PreComputeUnionReader(null, unionCaseInfo, null);
(FSharpFunction)FSharpUtils.Instance.PreComputeUnionConstructor(null, unionCaseInfo, null)); unionCase.Constructor = (FSharpFunction)FSharpUtils.PreComputeUnionConstructor(null, unionCaseInfo, null);
u.Cases.Add(unionCase); u.Cases.Add(unionCase);
} }
@ -124,15 +112,9 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (value == null) DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
{
writer.WriteNull();
return;
}
DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver;
Type unionType = UnionTypeLookupCache.Get(value.GetType()); Type unionType = UnionTypeLookupCache.Get(value.GetType());
Union union = UnionCache.Get(unionType); Union union = UnionCache.Get(unionType);
@ -145,7 +127,7 @@ namespace LC.Newtonsoft.Json.Converters
writer.WriteValue(caseInfo.Name); writer.WriteValue(caseInfo.Name);
if (caseInfo.Fields != null && caseInfo.Fields.Length > 0) if (caseInfo.Fields != null && caseInfo.Fields.Length > 0)
{ {
object[] fields = (object[])caseInfo.FieldReader.Invoke(value)!; object[] fields = (object[])caseInfo.FieldReader.Invoke(value);
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(FieldsPropertyName) : FieldsPropertyName); writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(FieldsPropertyName) : FieldsPropertyName);
writer.WriteStartArray(); writer.WriteStartArray();
@ -166,30 +148,30 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
if (reader.TokenType == JsonToken.Null) if (reader.TokenType == JsonToken.Null)
{ {
return null; return null;
} }
UnionCase? caseInfo = null; UnionCase caseInfo = null;
string? caseName = null; string caseName = null;
JArray? fields = null; JArray fields = null;
// start object // start object
reader.ReadAndAssert(); reader.ReadAndAssert();
while (reader.TokenType == JsonToken.PropertyName) while (reader.TokenType == JsonToken.PropertyName)
{ {
string propertyName = reader.Value!.ToString(); string propertyName = reader.Value.ToString();
if (string.Equals(propertyName, CasePropertyName, StringComparison.OrdinalIgnoreCase)) if (string.Equals(propertyName, CasePropertyName, StringComparison.OrdinalIgnoreCase))
{ {
reader.ReadAndAssert(); reader.ReadAndAssert();
Union union = UnionCache.Get(objectType); Union union = UnionCache.Get(objectType);
caseName = reader.Value!.ToString(); caseName = reader.Value.ToString();
caseInfo = union.Cases.SingleOrDefault(c => c.Name == caseName); caseInfo = union.Cases.SingleOrDefault(c => c.Name == caseName);
@ -221,7 +203,7 @@ namespace LC.Newtonsoft.Json.Converters
throw JsonSerializationException.Create(reader, "No '{0}' property with union name found.".FormatWith(CultureInfo.InvariantCulture, CasePropertyName)); throw JsonSerializationException.Create(reader, "No '{0}' property with union name found.".FormatWith(CultureInfo.InvariantCulture, CasePropertyName));
} }
object?[] typedFieldValues = new object?[caseInfo.Fields.Length]; object[] typedFieldValues = new object[caseInfo.Fields.Length];
if (caseInfo.Fields.Length > 0 && fields == null) if (caseInfo.Fields.Length > 0 && fields == null)
{ {
@ -290,7 +272,7 @@ namespace LC.Newtonsoft.Json.Converters
return false; return false;
} }
return (bool)FSharpUtils.Instance.IsUnion(null, objectType, null); return (bool)FSharpUtils.IsUnion(null, objectType, null);
} }
} }
} }

View File

@ -28,7 +28,6 @@ using System;
using LC.Newtonsoft.Json.Serialization; using LC.Newtonsoft.Json.Serialization;
using System.Globalization; using System.Globalization;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using System.Diagnostics;
namespace LC.Newtonsoft.Json.Converters namespace LC.Newtonsoft.Json.Converters
{ {
@ -43,7 +42,7 @@ namespace LC.Newtonsoft.Json.Converters
private const string TypePropertyName = "Type"; private const string TypePropertyName = "Type";
private const string ValuePropertyName = "Value"; private const string ValuePropertyName = "Value";
private static ReflectionObject? _reflectionObject; private static ReflectionObject _reflectionObject;
/// <summary> /// <summary>
/// Writes the JSON representation of the object. /// Writes the JSON representation of the object.
@ -51,23 +50,16 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (value == null)
{
writer.WriteNull();
return;
}
EnsureReflectionObject(value.GetType()); EnsureReflectionObject(value.GetType());
MiscellaneousUtils.Assert(_reflectionObject != null);
DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
string keyName = (string)_reflectionObject.GetValue(value, KeyPropertyName)!; string keyName = (string)_reflectionObject.GetValue(value, KeyPropertyName);
object? keyValue = _reflectionObject.GetValue(value, ValuePropertyName); object keyValue = _reflectionObject.GetValue(value, ValuePropertyName);
Type? keyValueType = keyValue?.GetType(); Type keyValueType = keyValue?.GetType();
writer.WriteStartObject(); writer.WriteStartObject();
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyPropertyName) : KeyPropertyName); writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyPropertyName) : KeyPropertyName);
@ -79,7 +71,7 @@ namespace LC.Newtonsoft.Json.Converters
if (keyValueType != null) if (keyValueType != null)
{ {
if (JsonSerializerInternalWriter.TryConvertToString(keyValue!, keyValueType, out string? valueJson)) if (JsonSerializerInternalWriter.TryConvertToString(keyValue, keyValueType, out string valueJson))
{ {
writer.WriteValue(valueJson); writer.WriteValue(valueJson);
} }
@ -100,7 +92,7 @@ namespace LC.Newtonsoft.Json.Converters
{ {
reader.ReadAndAssert(); reader.ReadAndAssert();
if (reader.TokenType != JsonToken.PropertyName || !string.Equals(reader.Value?.ToString(), propertyName, StringComparison.OrdinalIgnoreCase)) if (reader.TokenType != JsonToken.PropertyName || !string.Equals(reader.Value.ToString(), propertyName, StringComparison.OrdinalIgnoreCase))
{ {
throw new JsonSerializationException("Expected JSON property '{0}'.".FormatWith(CultureInfo.InvariantCulture, propertyName)); throw new JsonSerializationException("Expected JSON property '{0}'.".FormatWith(CultureInfo.InvariantCulture, propertyName));
} }
@ -114,20 +106,19 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
EnsureReflectionObject(objectType); EnsureReflectionObject(objectType);
MiscellaneousUtils.Assert(_reflectionObject != null);
object entityKeyMember = _reflectionObject.Creator!(); object entityKeyMember = _reflectionObject.Creator();
ReadAndAssertProperty(reader, KeyPropertyName); ReadAndAssertProperty(reader, KeyPropertyName);
reader.ReadAndAssert(); reader.ReadAndAssert();
_reflectionObject.SetValue(entityKeyMember, KeyPropertyName, reader.Value?.ToString()); _reflectionObject.SetValue(entityKeyMember, KeyPropertyName, reader.Value.ToString());
ReadAndAssertProperty(reader, TypePropertyName); ReadAndAssertProperty(reader, TypePropertyName);
reader.ReadAndAssert(); reader.ReadAndAssert();
string? type = reader.Value?.ToString(); string type = reader.Value.ToString();
Type t = Type.GetType(type); Type t = Type.GetType(type);

View File

@ -46,7 +46,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
// can write is set to false // can write is set to false
} }
@ -59,12 +59,12 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
return ReadValue(reader); return ReadValue(reader);
} }
private object? ReadValue(JsonReader reader) private object ReadValue(JsonReader reader)
{ {
if (!reader.MoveToContent()) if (!reader.MoveToContent())
{ {
@ -89,7 +89,7 @@ namespace LC.Newtonsoft.Json.Converters
private object ReadList(JsonReader reader) private object ReadList(JsonReader reader)
{ {
IList<object?> list = new List<object?>(); IList<object> list = new List<object>();
while (reader.Read()) while (reader.Read())
{ {
@ -98,7 +98,7 @@ namespace LC.Newtonsoft.Json.Converters
case JsonToken.Comment: case JsonToken.Comment:
break; break;
default: default:
object? v = ReadValue(reader); object v = ReadValue(reader);
list.Add(v); list.Add(v);
break; break;
@ -112,21 +112,21 @@ namespace LC.Newtonsoft.Json.Converters
private object ReadObject(JsonReader reader) private object ReadObject(JsonReader reader)
{ {
IDictionary<string, object?> expandoObject = new ExpandoObject(); IDictionary<string, object> expandoObject = new ExpandoObject();
while (reader.Read()) while (reader.Read())
{ {
switch (reader.TokenType) switch (reader.TokenType)
{ {
case JsonToken.PropertyName: case JsonToken.PropertyName:
string propertyName = reader.Value!.ToString(); string propertyName = reader.Value.ToString();
if (!reader.Read()) if (!reader.Read())
{ {
throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
} }
object? v = ReadValue(reader); object v = ReadValue(reader);
expandoObject[propertyName] = v; expandoObject[propertyName] = v;
break; break;

View File

@ -37,8 +37,8 @@ namespace LC.Newtonsoft.Json.Converters
private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind; private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind;
private string? _dateTimeFormat; private string _dateTimeFormat;
private CultureInfo? _culture; private CultureInfo _culture;
/// <summary> /// <summary>
/// Gets or sets the date time styles used when converting a date to and from JSON. /// Gets or sets the date time styles used when converting a date to and from JSON.
@ -54,10 +54,10 @@ namespace LC.Newtonsoft.Json.Converters
/// Gets or sets the date time format used when converting a date to and from JSON. /// Gets or sets the date time format used when converting a date to and from JSON.
/// </summary> /// </summary>
/// <value>The date time format used when converting a date to and from JSON.</value> /// <value>The date time format used when converting a date to and from JSON.</value>
public string? DateTimeFormat public string DateTimeFormat
{ {
get => _dateTimeFormat ?? string.Empty; get => _dateTimeFormat ?? string.Empty;
set => _dateTimeFormat = (StringUtils.IsNullOrEmpty(value)) ? null : value; set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value;
} }
/// <summary> /// <summary>
@ -76,7 +76,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
string text; string text;
@ -104,7 +104,7 @@ namespace LC.Newtonsoft.Json.Converters
#endif #endif
else else
{ {
throw new JsonSerializationException("Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.".FormatWith(CultureInfo.InvariantCulture, ReflectionUtils.GetObjectType(value)!)); throw new JsonSerializationException("Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.".FormatWith(CultureInfo.InvariantCulture, ReflectionUtils.GetObjectType(value)));
} }
writer.WriteValue(text); writer.WriteValue(text);
@ -118,7 +118,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
bool nullable = ReflectionUtils.IsNullableType(objectType); bool nullable = ReflectionUtils.IsNullableType(objectType);
if (reader.TokenType == JsonToken.Null) if (reader.TokenType == JsonToken.Null)
@ -142,7 +142,7 @@ namespace LC.Newtonsoft.Json.Converters
#if HAVE_DATE_TIME_OFFSET #if HAVE_DATE_TIME_OFFSET
if (t == typeof(DateTimeOffset)) if (t == typeof(DateTimeOffset))
{ {
return (reader.Value is DateTimeOffset) ? reader.Value : new DateTimeOffset((DateTime)reader.Value!); return (reader.Value is DateTimeOffset) ? reader.Value : new DateTimeOffset((DateTime)reader.Value);
} }
// converter is expected to return a DateTime // converter is expected to return a DateTime
@ -160,9 +160,9 @@ namespace LC.Newtonsoft.Json.Converters
throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
} }
string? dateText = reader.Value?.ToString(); string dateText = reader.Value.ToString();
if (StringUtils.IsNullOrEmpty(dateText) && nullable) if (string.IsNullOrEmpty(dateText) && nullable)
{ {
return null; return null;
} }
@ -170,7 +170,7 @@ namespace LC.Newtonsoft.Json.Converters
#if HAVE_DATE_TIME_OFFSET #if HAVE_DATE_TIME_OFFSET
if (t == typeof(DateTimeOffset)) if (t == typeof(DateTimeOffset))
{ {
if (!StringUtils.IsNullOrEmpty(_dateTimeFormat)) if (!string.IsNullOrEmpty(_dateTimeFormat))
{ {
return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles); return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles);
} }
@ -181,7 +181,7 @@ namespace LC.Newtonsoft.Json.Converters
} }
#endif #endif
if (!StringUtils.IsNullOrEmpty(_dateTimeFormat)) if (!string.IsNullOrEmpty(_dateTimeFormat))
{ {
return DateTime.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles); return DateTime.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles);
} }

View File

@ -40,7 +40,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
long ticks; long ticks;
@ -74,7 +74,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing property value of the JSON that is being converted.</param> /// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
if (reader.TokenType == JsonToken.Null) if (reader.TokenType == JsonToken.Null)
{ {
@ -86,12 +86,12 @@ namespace LC.Newtonsoft.Json.Converters
return null; return null;
} }
if (reader.TokenType != JsonToken.StartConstructor || !string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) if (reader.TokenType != JsonToken.StartConstructor || !string.Equals(reader.Value.ToString(), "Date", StringComparison.Ordinal))
{ {
throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing date. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value)); throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing date. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value));
} }
if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime d, out string? errorMessage)) if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime d, out string errorMessage))
{ {
throw JsonSerializationException.Create(reader, errorMessage); throw JsonSerializationException.Create(reader, errorMessage);
} }

View File

@ -56,17 +56,11 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (value == null)
{
writer.WriteNull();
return;
}
ReflectionObject reflectionObject = ReflectionObjectPerType.Get(value.GetType()); ReflectionObject reflectionObject = ReflectionObjectPerType.Get(value.GetType());
DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
writer.WriteStartObject(); writer.WriteStartObject();
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyName) : KeyName); writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyName) : KeyName);
@ -84,7 +78,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
if (reader.TokenType == JsonToken.Null) if (reader.TokenType == JsonToken.Null)
{ {
@ -96,8 +90,8 @@ namespace LC.Newtonsoft.Json.Converters
return null; return null;
} }
object? key = null; object key = null;
object? value = null; object value = null;
reader.ReadAndAssert(); reader.ReadAndAssert();
@ -111,7 +105,7 @@ namespace LC.Newtonsoft.Json.Converters
while (reader.TokenType == JsonToken.PropertyName) while (reader.TokenType == JsonToken.PropertyName)
{ {
string propertyName = reader.Value!.ToString(); string propertyName = reader.Value.ToString();
if (string.Equals(propertyName, KeyName, StringComparison.OrdinalIgnoreCase)) if (string.Equals(propertyName, KeyName, StringComparison.OrdinalIgnoreCase))
{ {
reader.ReadForTypeAndAssert(keyContract, false); reader.ReadForTypeAndAssert(keyContract, false);
@ -132,7 +126,7 @@ namespace LC.Newtonsoft.Json.Converters
reader.ReadAndAssert(); reader.ReadAndAssert();
} }
return reflectionObject.Creator!(key, value); return reflectionObject.Creator(key, value);
} }
/// <summary> /// <summary>

View File

@ -47,7 +47,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (value == null) if (value == null)
{ {
@ -84,7 +84,7 @@ namespace LC.Newtonsoft.Json.Converters
// 'l' to make \w, \W, etc. locale dependent, 's' for dotall mode // 'l' to make \w, \W, etc. locale dependent, 's' for dotall mode
// ('.' matches everything), and 'u' to make \w, \W, etc. match unicode. // ('.' matches everything), and 'u' to make \w, \W, etc. match unicode.
string? options = null; string options = null;
if (HasFlag(regex.Options, RegexOptions.IgnoreCase)) if (HasFlag(regex.Options, RegexOptions.IgnoreCase))
{ {
@ -114,7 +114,7 @@ namespace LC.Newtonsoft.Json.Converters
private void WriteJson(JsonWriter writer, Regex regex, JsonSerializer serializer) private void WriteJson(JsonWriter writer, Regex regex, JsonSerializer serializer)
{ {
DefaultContractResolver? resolver = serializer.ContractResolver as DefaultContractResolver; DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
writer.WriteStartObject(); writer.WriteStartObject();
writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(PatternName) : PatternName); writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(PatternName) : PatternName);
@ -132,7 +132,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
switch (reader.TokenType) switch (reader.TokenType)
{ {
@ -149,7 +149,7 @@ namespace LC.Newtonsoft.Json.Converters
private object ReadRegexString(JsonReader reader) private object ReadRegexString(JsonReader reader)
{ {
string regexText = (string)reader.Value!; string regexText = (string)reader.Value;
if (regexText.Length > 0 && regexText[0] == '/') if (regexText.Length > 0 && regexText[0] == '/')
{ {
@ -171,7 +171,7 @@ namespace LC.Newtonsoft.Json.Converters
private Regex ReadRegexObject(JsonReader reader, JsonSerializer serializer) private Regex ReadRegexObject(JsonReader reader, JsonSerializer serializer)
{ {
string? pattern = null; string pattern = null;
RegexOptions? options = null; RegexOptions? options = null;
while (reader.Read()) while (reader.Read())
@ -179,7 +179,7 @@ namespace LC.Newtonsoft.Json.Converters
switch (reader.TokenType) switch (reader.TokenType)
{ {
case JsonToken.PropertyName: case JsonToken.PropertyName:
string propertyName = reader.Value!.ToString(); string propertyName = reader.Value.ToString();
if (!reader.Read()) if (!reader.Read())
{ {
@ -188,7 +188,7 @@ namespace LC.Newtonsoft.Json.Converters
if (string.Equals(propertyName, PatternName, StringComparison.OrdinalIgnoreCase)) if (string.Equals(propertyName, PatternName, StringComparison.OrdinalIgnoreCase))
{ {
pattern = (string?)reader.Value; pattern = (string)reader.Value;
} }
else if (string.Equals(propertyName, OptionsName, StringComparison.OrdinalIgnoreCase)) else if (string.Equals(propertyName, OptionsName, StringComparison.OrdinalIgnoreCase))
{ {

View File

@ -82,7 +82,7 @@ namespace LC.Newtonsoft.Json.Converters
/// Gets or sets the naming strategy used to resolve how enum text is written. /// Gets or sets the naming strategy used to resolve how enum text is written.
/// </summary> /// </summary>
/// <value>The naming strategy used to resolve how enum text is written.</value> /// <value>The naming strategy used to resolve how enum text is written.</value>
public NamingStrategy? NamingStrategy { get; set; } public NamingStrategy NamingStrategy { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether integer values are allowed when serializing and deserializing. /// Gets or sets a value indicating whether integer values are allowed when serializing and deserializing.
@ -175,7 +175,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (value == null) if (value == null)
{ {
@ -185,7 +185,7 @@ namespace LC.Newtonsoft.Json.Converters
Enum e = (Enum)value; Enum e = (Enum)value;
if (!EnumUtils.TryToString(e.GetType(), value, NamingStrategy, out string? enumName)) if (!EnumUtils.TryToString(e.GetType(), value, NamingStrategy, out string enumName))
{ {
if (!AllowIntegerValues) if (!AllowIntegerValues)
{ {
@ -209,7 +209,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
if (reader.TokenType == JsonToken.Null) if (reader.TokenType == JsonToken.Null)
{ {
@ -228,14 +228,14 @@ namespace LC.Newtonsoft.Json.Converters
{ {
if (reader.TokenType == JsonToken.String) if (reader.TokenType == JsonToken.String)
{ {
string? enumText = reader.Value?.ToString(); string enumText = reader.Value.ToString();
if (StringUtils.IsNullOrEmpty(enumText) && isNullable) if (enumText == string.Empty && isNullable)
{ {
return null; return null;
} }
return EnumUtils.ParseEnum(t, NamingStrategy, enumText!, !AllowIntegerValues); return EnumUtils.ParseEnum(t, NamingStrategy, enumText, !AllowIntegerValues);
} }
if (reader.TokenType == JsonToken.Integer) if (reader.TokenType == JsonToken.Integer)

View File

@ -42,7 +42,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
long seconds; long seconds;
@ -77,7 +77,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing property value of the JSON that is being converted.</param> /// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
bool nullable = ReflectionUtils.IsNullable(objectType); bool nullable = ReflectionUtils.IsNullable(objectType);
if (reader.TokenType == JsonToken.Null) if (reader.TokenType == JsonToken.Null)
@ -94,11 +94,11 @@ namespace LC.Newtonsoft.Json.Converters
if (reader.TokenType == JsonToken.Integer) if (reader.TokenType == JsonToken.Integer)
{ {
seconds = (long)reader.Value!; seconds = (long)reader.Value;
} }
else if (reader.TokenType == JsonToken.String) else if (reader.TokenType == JsonToken.String)
{ {
if (!long.TryParse((string)reader.Value!, out seconds)) if (!long.TryParse((string)reader.Value, out seconds))
{ {
throw JsonSerializationException.Create(reader, "Cannot convert invalid value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); throw JsonSerializationException.Create(reader, "Cannot convert invalid value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
} }

View File

@ -40,7 +40,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (value == null) if (value == null)
{ {
@ -64,7 +64,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing property value of the JSON that is being converted.</param> /// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
if (reader.TokenType == JsonToken.Null) if (reader.TokenType == JsonToken.Null)
{ {
@ -76,7 +76,7 @@ namespace LC.Newtonsoft.Json.Converters
{ {
try try
{ {
Version v = new Version((string)reader.Value!); Version v = new Version((string)reader.Value);
return v; return v;
} }
catch (Exception ex) catch (Exception ex)

View File

@ -38,7 +38,6 @@ using System.Xml.Linq;
#endif #endif
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Diagnostics.CodeAnalysis;
namespace LC.Newtonsoft.Json.Converters namespace LC.Newtonsoft.Json.Converters
{ {
@ -54,44 +53,44 @@ namespace LC.Newtonsoft.Json.Converters
_document = document; _document = document;
} }
public IXmlNode CreateComment(string? data) public IXmlNode CreateComment(string data)
{ {
return new XmlNodeWrapper(_document.CreateComment(data)); return new XmlNodeWrapper(_document.CreateComment(data));
} }
public IXmlNode CreateTextNode(string? text) public IXmlNode CreateTextNode(string text)
{ {
return new XmlNodeWrapper(_document.CreateTextNode(text)); return new XmlNodeWrapper(_document.CreateTextNode(text));
} }
public IXmlNode CreateCDataSection(string? data) public IXmlNode CreateCDataSection(string data)
{ {
return new XmlNodeWrapper(_document.CreateCDataSection(data)); return new XmlNodeWrapper(_document.CreateCDataSection(data));
} }
public IXmlNode CreateWhitespace(string? text) public IXmlNode CreateWhitespace(string text)
{ {
return new XmlNodeWrapper(_document.CreateWhitespace(text)); return new XmlNodeWrapper(_document.CreateWhitespace(text));
} }
public IXmlNode CreateSignificantWhitespace(string? text) public IXmlNode CreateSignificantWhitespace(string text)
{ {
return new XmlNodeWrapper(_document.CreateSignificantWhitespace(text)); return new XmlNodeWrapper(_document.CreateSignificantWhitespace(text));
} }
public IXmlNode CreateXmlDeclaration(string? version, string? encoding, string? standalone) public IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone)
{ {
return new XmlDeclarationWrapper(_document.CreateXmlDeclaration(version, encoding, standalone)); return new XmlDeclarationWrapper(_document.CreateXmlDeclaration(version, encoding, standalone));
} }
#if HAVE_XML_DOCUMENT_TYPE #if HAVE_XML_DOCUMENT_TYPE
public IXmlNode CreateXmlDocumentType(string? name, string? publicId, string? systemId, string? internalSubset) public IXmlNode CreateXmlDocumentType(string name, string publicId, string systemId, string internalSubset)
{ {
return new XmlDocumentTypeWrapper(_document.CreateDocumentType(name, publicId, systemId, null)); return new XmlDocumentTypeWrapper(_document.CreateDocumentType(name, publicId, systemId, null));
} }
#endif #endif
public IXmlNode CreateProcessingInstruction(string target, string? data) public IXmlNode CreateProcessingInstruction(string target, string data)
{ {
return new XmlNodeWrapper(_document.CreateProcessingInstruction(target, data)); return new XmlNodeWrapper(_document.CreateProcessingInstruction(target, data));
} }
@ -106,7 +105,7 @@ namespace LC.Newtonsoft.Json.Converters
return new XmlElementWrapper(_document.CreateElement(qualifiedName, namespaceUri)); return new XmlElementWrapper(_document.CreateElement(qualifiedName, namespaceUri));
} }
public IXmlNode CreateAttribute(string name, string? value) public IXmlNode CreateAttribute(string name, string value)
{ {
XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(name)); XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(name));
attribute.Value = value; attribute.Value = value;
@ -114,7 +113,7 @@ namespace LC.Newtonsoft.Json.Converters
return attribute; return attribute;
} }
public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string? value) public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value)
{ {
XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(qualifiedName, namespaceUri)); XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(qualifiedName, namespaceUri));
attribute.Value = value; attribute.Value = value;
@ -122,7 +121,7 @@ namespace LC.Newtonsoft.Json.Converters
return attribute; return attribute;
} }
public IXmlElement? DocumentElement public IXmlElement DocumentElement
{ {
get get
{ {
@ -150,7 +149,7 @@ namespace LC.Newtonsoft.Json.Converters
{ {
XmlNodeWrapper xmlAttributeWrapper = (XmlNodeWrapper)attribute; XmlNodeWrapper xmlAttributeWrapper = (XmlNodeWrapper)attribute;
_element.SetAttributeNode((XmlAttribute)xmlAttributeWrapper.WrappedNode!); _element.SetAttributeNode((XmlAttribute)xmlAttributeWrapper.WrappedNode);
} }
public string GetPrefixOfNamespace(string namespaceUri) public string GetPrefixOfNamespace(string namespaceUri)
@ -205,26 +204,26 @@ namespace LC.Newtonsoft.Json.Converters
public string InternalSubset => _documentType.InternalSubset; public string InternalSubset => _documentType.InternalSubset;
public override string? LocalName => "DOCTYPE"; public override string LocalName => "DOCTYPE";
} }
#endif #endif
internal class XmlNodeWrapper : IXmlNode internal class XmlNodeWrapper : IXmlNode
{ {
private readonly XmlNode _node; private readonly XmlNode _node;
private List<IXmlNode>? _childNodes; private List<IXmlNode> _childNodes;
private List<IXmlNode>? _attributes; private List<IXmlNode> _attributes;
public XmlNodeWrapper(XmlNode node) public XmlNodeWrapper(XmlNode node)
{ {
_node = node; _node = node;
} }
public object? WrappedNode => _node; public object WrappedNode => _node;
public XmlNodeType NodeType => _node.NodeType; public XmlNodeType NodeType => _node.NodeType;
public virtual string? LocalName => _node.LocalName; public virtual string LocalName => _node.LocalName;
public List<IXmlNode> ChildNodes public List<IXmlNode> ChildNodes
{ {
@ -310,7 +309,7 @@ namespace LC.Newtonsoft.Json.Converters
} }
} }
public IXmlNode? ParentNode public IXmlNode ParentNode
{ {
get get
{ {
@ -325,7 +324,7 @@ namespace LC.Newtonsoft.Json.Converters
} }
} }
public string? Value public string Value
{ {
get => _node.Value; get => _node.Value;
set => _node.Value = value; set => _node.Value = value;
@ -341,7 +340,7 @@ namespace LC.Newtonsoft.Json.Converters
return newChild; return newChild;
} }
public string? NamespaceUri => _node.NamespaceURI; public string NamespaceUri => _node.NamespaceURI;
} }
#endif #endif
#endregion #endregion
@ -349,22 +348,22 @@ namespace LC.Newtonsoft.Json.Converters
#region Interfaces #region Interfaces
internal interface IXmlDocument : IXmlNode internal interface IXmlDocument : IXmlNode
{ {
IXmlNode CreateComment(string? text); IXmlNode CreateComment(string text);
IXmlNode CreateTextNode(string? text); IXmlNode CreateTextNode(string text);
IXmlNode CreateCDataSection(string? data); IXmlNode CreateCDataSection(string data);
IXmlNode CreateWhitespace(string? text); IXmlNode CreateWhitespace(string text);
IXmlNode CreateSignificantWhitespace(string? text); IXmlNode CreateSignificantWhitespace(string text);
IXmlNode CreateXmlDeclaration(string? version, string? encoding, string? standalone); IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone);
#if HAVE_XML_DOCUMENT_TYPE #if HAVE_XML_DOCUMENT_TYPE
IXmlNode CreateXmlDocumentType(string? name, string? publicId, string? systemId, string? internalSubset); IXmlNode CreateXmlDocumentType(string name, string publicId, string systemId, string internalSubset);
#endif #endif
IXmlNode CreateProcessingInstruction(string target, string? data); IXmlNode CreateProcessingInstruction(string target, string data);
IXmlElement CreateElement(string elementName); IXmlElement CreateElement(string elementName);
IXmlElement CreateElement(string qualifiedName, string namespaceUri); IXmlElement CreateElement(string qualifiedName, string namespaceUri);
IXmlNode CreateAttribute(string name, string? value); IXmlNode CreateAttribute(string name, string value);
IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string? value); IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value);
IXmlElement? DocumentElement { get; } IXmlElement DocumentElement { get; }
} }
internal interface IXmlDeclaration : IXmlNode internal interface IXmlDeclaration : IXmlNode
@ -392,14 +391,14 @@ namespace LC.Newtonsoft.Json.Converters
internal interface IXmlNode internal interface IXmlNode
{ {
XmlNodeType NodeType { get; } XmlNodeType NodeType { get; }
string? LocalName { get; } string LocalName { get; }
List<IXmlNode> ChildNodes { get; } List<IXmlNode> ChildNodes { get; }
List<IXmlNode> Attributes { get; } List<IXmlNode> Attributes { get; }
IXmlNode? ParentNode { get; } IXmlNode ParentNode { get; }
string? Value { get; set; } string Value { get; set; }
IXmlNode AppendChild(IXmlNode newChild); IXmlNode AppendChild(IXmlNode newChild);
string? NamespaceUri { get; } string NamespaceUri { get; }
object? WrappedNode { get; } object WrappedNode { get; }
} }
#endregion #endregion
@ -450,12 +449,12 @@ namespace LC.Newtonsoft.Json.Converters
public string InternalSubset => _documentType.InternalSubset; public string InternalSubset => _documentType.InternalSubset;
public override string? LocalName => "DOCTYPE"; public override string LocalName => "DOCTYPE";
} }
internal class XDocumentWrapper : XContainerWrapper, IXmlDocument internal class XDocumentWrapper : XContainerWrapper, IXmlDocument
{ {
private XDocument Document => (XDocument)WrappedNode!; private XDocument Document => (XDocument)WrappedNode;
public XDocumentWrapper(XDocument document) public XDocumentWrapper(XDocument document)
: base(document) : base(document)
@ -489,42 +488,42 @@ namespace LC.Newtonsoft.Json.Converters
} }
} }
public IXmlNode CreateComment(string? text) public IXmlNode CreateComment(string text)
{ {
return new XObjectWrapper(new XComment(text)); return new XObjectWrapper(new XComment(text));
} }
public IXmlNode CreateTextNode(string? text) public IXmlNode CreateTextNode(string text)
{ {
return new XObjectWrapper(new XText(text)); return new XObjectWrapper(new XText(text));
} }
public IXmlNode CreateCDataSection(string? data) public IXmlNode CreateCDataSection(string data)
{ {
return new XObjectWrapper(new XCData(data)); return new XObjectWrapper(new XCData(data));
} }
public IXmlNode CreateWhitespace(string? text) public IXmlNode CreateWhitespace(string text)
{ {
return new XObjectWrapper(new XText(text)); return new XObjectWrapper(new XText(text));
} }
public IXmlNode CreateSignificantWhitespace(string? text) public IXmlNode CreateSignificantWhitespace(string text)
{ {
return new XObjectWrapper(new XText(text)); return new XObjectWrapper(new XText(text));
} }
public IXmlNode CreateXmlDeclaration(string? version, string? encoding, string? standalone) public IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone)
{ {
return new XDeclarationWrapper(new XDeclaration(version, encoding, standalone)); return new XDeclarationWrapper(new XDeclaration(version, encoding, standalone));
} }
public IXmlNode CreateXmlDocumentType(string? name, string? publicId, string? systemId, string? internalSubset) public IXmlNode CreateXmlDocumentType(string name, string publicId, string systemId, string internalSubset)
{ {
return new XDocumentTypeWrapper(new XDocumentType(name, publicId, systemId, internalSubset)); return new XDocumentTypeWrapper(new XDocumentType(name, publicId, systemId, internalSubset));
} }
public IXmlNode CreateProcessingInstruction(string target, string? data) public IXmlNode CreateProcessingInstruction(string target, string data)
{ {
return new XProcessingInstructionWrapper(new XProcessingInstruction(target, data)); return new XProcessingInstructionWrapper(new XProcessingInstruction(target, data));
} }
@ -540,18 +539,18 @@ namespace LC.Newtonsoft.Json.Converters
return new XElementWrapper(new XElement(XName.Get(localName, namespaceUri))); return new XElementWrapper(new XElement(XName.Get(localName, namespaceUri)));
} }
public IXmlNode CreateAttribute(string name, string? value) public IXmlNode CreateAttribute(string name, string value)
{ {
return new XAttributeWrapper(new XAttribute(name, value)); return new XAttributeWrapper(new XAttribute(name, value));
} }
public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string? value) public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value)
{ {
string localName = MiscellaneousUtils.GetLocalName(qualifiedName); string localName = MiscellaneousUtils.GetLocalName(qualifiedName);
return new XAttributeWrapper(new XAttribute(XName.Get(localName, namespaceUri), value)); return new XAttributeWrapper(new XAttribute(XName.Get(localName, namespaceUri), value));
} }
public IXmlElement? DocumentElement public IXmlElement DocumentElement
{ {
get get
{ {
@ -580,20 +579,20 @@ namespace LC.Newtonsoft.Json.Converters
internal class XTextWrapper : XObjectWrapper internal class XTextWrapper : XObjectWrapper
{ {
private XText Text => (XText)WrappedNode!; private XText Text => (XText)WrappedNode;
public XTextWrapper(XText text) public XTextWrapper(XText text)
: base(text) : base(text)
{ {
} }
public override string? Value public override string Value
{ {
get => Text.Value; get => Text.Value;
set => Text.Value = value; set => Text.Value = value;
} }
public override IXmlNode? ParentNode public override IXmlNode ParentNode
{ {
get get
{ {
@ -609,20 +608,20 @@ namespace LC.Newtonsoft.Json.Converters
internal class XCommentWrapper : XObjectWrapper internal class XCommentWrapper : XObjectWrapper
{ {
private XComment Text => (XComment)WrappedNode!; private XComment Text => (XComment)WrappedNode;
public XCommentWrapper(XComment text) public XCommentWrapper(XComment text)
: base(text) : base(text)
{ {
} }
public override string? Value public override string Value
{ {
get => Text.Value; get => Text.Value;
set => Text.Value = value; set => Text.Value = value;
} }
public override IXmlNode? ParentNode public override IXmlNode ParentNode
{ {
get get
{ {
@ -638,16 +637,16 @@ namespace LC.Newtonsoft.Json.Converters
internal class XProcessingInstructionWrapper : XObjectWrapper internal class XProcessingInstructionWrapper : XObjectWrapper
{ {
private XProcessingInstruction ProcessingInstruction => (XProcessingInstruction)WrappedNode!; private XProcessingInstruction ProcessingInstruction => (XProcessingInstruction)WrappedNode;
public XProcessingInstructionWrapper(XProcessingInstruction processingInstruction) public XProcessingInstructionWrapper(XProcessingInstruction processingInstruction)
: base(processingInstruction) : base(processingInstruction)
{ {
} }
public override string? LocalName => ProcessingInstruction.Target; public override string LocalName => ProcessingInstruction.Target;
public override string? Value public override string Value
{ {
get => ProcessingInstruction.Data; get => ProcessingInstruction.Data;
set => ProcessingInstruction.Data = value; set => ProcessingInstruction.Data = value;
@ -656,9 +655,9 @@ namespace LC.Newtonsoft.Json.Converters
internal class XContainerWrapper : XObjectWrapper internal class XContainerWrapper : XObjectWrapper
{ {
private List<IXmlNode>? _childNodes; private List<IXmlNode> _childNodes;
private XContainer Container => (XContainer)WrappedNode!; private XContainer Container => (XContainer)WrappedNode;
public XContainerWrapper(XContainer container) public XContainerWrapper(XContainer container)
: base(container) : base(container)
@ -693,7 +692,7 @@ namespace LC.Newtonsoft.Json.Converters
protected virtual bool HasChildNodes => Container.LastNode != null; protected virtual bool HasChildNodes => Container.LastNode != null;
public override IXmlNode? ParentNode public override IXmlNode ParentNode
{ {
get get
{ {
@ -762,26 +761,26 @@ namespace LC.Newtonsoft.Json.Converters
internal class XObjectWrapper : IXmlNode internal class XObjectWrapper : IXmlNode
{ {
private readonly XObject? _xmlObject; private readonly XObject _xmlObject;
public XObjectWrapper(XObject? xmlObject) public XObjectWrapper(XObject xmlObject)
{ {
_xmlObject = xmlObject; _xmlObject = xmlObject;
} }
public object? WrappedNode => _xmlObject; public object WrappedNode => _xmlObject;
public virtual XmlNodeType NodeType => _xmlObject?.NodeType ?? XmlNodeType.None; public virtual XmlNodeType NodeType => _xmlObject.NodeType;
public virtual string? LocalName => null; public virtual string LocalName => null;
public virtual List<IXmlNode> ChildNodes => XmlNodeConverter.EmptyChildNodes; public virtual List<IXmlNode> ChildNodes => XmlNodeConverter.EmptyChildNodes;
public virtual List<IXmlNode> Attributes => XmlNodeConverter.EmptyChildNodes; public virtual List<IXmlNode> Attributes => XmlNodeConverter.EmptyChildNodes;
public virtual IXmlNode? ParentNode => null; public virtual IXmlNode ParentNode => null;
public virtual string? Value public virtual string Value
{ {
get => null; get => null;
set => throw new InvalidOperationException(); set => throw new InvalidOperationException();
@ -792,29 +791,29 @@ namespace LC.Newtonsoft.Json.Converters
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
public virtual string? NamespaceUri => null; public virtual string NamespaceUri => null;
} }
internal class XAttributeWrapper : XObjectWrapper internal class XAttributeWrapper : XObjectWrapper
{ {
private XAttribute Attribute => (XAttribute)WrappedNode!; private XAttribute Attribute => (XAttribute)WrappedNode;
public XAttributeWrapper(XAttribute attribute) public XAttributeWrapper(XAttribute attribute)
: base(attribute) : base(attribute)
{ {
} }
public override string? Value public override string Value
{ {
get => Attribute.Value; get => Attribute.Value;
set => Attribute.Value = value; set => Attribute.Value = value;
} }
public override string? LocalName => Attribute.Name.LocalName; public override string LocalName => Attribute.Name.LocalName;
public override string? NamespaceUri => Attribute.Name.NamespaceName; public override string NamespaceUri => Attribute.Name.NamespaceName;
public override IXmlNode? ParentNode public override IXmlNode ParentNode
{ {
get get
{ {
@ -830,9 +829,9 @@ namespace LC.Newtonsoft.Json.Converters
internal class XElementWrapper : XContainerWrapper, IXmlElement internal class XElementWrapper : XContainerWrapper, IXmlElement
{ {
private List<IXmlNode>? _attributes; private List<IXmlNode> _attributes;
private XElement Element => (XElement)WrappedNode!; private XElement Element => (XElement)WrappedNode;
public XElementWrapper(XElement element) public XElementWrapper(XElement element)
: base(element) : base(element)
@ -854,7 +853,7 @@ namespace LC.Newtonsoft.Json.Converters
// cache results to prevent multiple reads which kills perf in large documents // cache results to prevent multiple reads which kills perf in large documents
if (_attributes == null) if (_attributes == null)
{ {
if (!Element.HasAttributes && !HasImplicitNamespaceAttribute(NamespaceUri!)) if (!Element.HasAttributes && !HasImplicitNamespaceAttribute(NamespaceUri))
{ {
_attributes = XmlNodeConverter.EmptyChildNodes; _attributes = XmlNodeConverter.EmptyChildNodes;
} }
@ -868,7 +867,7 @@ namespace LC.Newtonsoft.Json.Converters
// ensure elements created with a namespace but no namespace attribute are converted correctly // ensure elements created with a namespace but no namespace attribute are converted correctly
// e.g. new XElement("{http://example.com}MyElement"); // e.g. new XElement("{http://example.com}MyElement");
string namespaceUri = NamespaceUri!; string namespaceUri = NamespaceUri;
if (HasImplicitNamespaceAttribute(namespaceUri)) if (HasImplicitNamespaceAttribute(namespaceUri))
{ {
_attributes.Insert(0, new XAttributeWrapper(new XAttribute("xmlns", namespaceUri))); _attributes.Insert(0, new XAttributeWrapper(new XAttribute("xmlns", namespaceUri)));
@ -882,9 +881,9 @@ namespace LC.Newtonsoft.Json.Converters
private bool HasImplicitNamespaceAttribute(string namespaceUri) private bool HasImplicitNamespaceAttribute(string namespaceUri)
{ {
if (!StringUtils.IsNullOrEmpty(namespaceUri) && namespaceUri != ParentNode?.NamespaceUri) if (!string.IsNullOrEmpty(namespaceUri) && namespaceUri != ParentNode?.NamespaceUri)
{ {
if (StringUtils.IsNullOrEmpty(GetPrefixOfNamespace(namespaceUri))) if (string.IsNullOrEmpty(GetPrefixOfNamespace(namespaceUri)))
{ {
bool namespaceDeclared = false; bool namespaceDeclared = false;
@ -892,7 +891,7 @@ namespace LC.Newtonsoft.Json.Converters
{ {
foreach (XAttribute attribute in Element.Attributes()) foreach (XAttribute attribute in Element.Attributes())
{ {
if (attribute.Name.LocalName == "xmlns" && StringUtils.IsNullOrEmpty(attribute.Name.NamespaceName) && attribute.Value == namespaceUri) if (attribute.Name.LocalName == "xmlns" && string.IsNullOrEmpty(attribute.Name.NamespaceName) && attribute.Value == namespaceUri)
{ {
namespaceDeclared = true; namespaceDeclared = true;
} }
@ -916,15 +915,15 @@ namespace LC.Newtonsoft.Json.Converters
return result; return result;
} }
public override string? Value public override string Value
{ {
get => Element.Value; get => Element.Value;
set => Element.Value = value; set => Element.Value = value;
} }
public override string? LocalName => Element.Name.LocalName; public override string LocalName => Element.Name.LocalName;
public override string? NamespaceUri => Element.Name.NamespaceName; public override string NamespaceUri => Element.Name.NamespaceName;
public string GetPrefixOfNamespace(string namespaceUri) public string GetPrefixOfNamespace(string namespaceUri)
{ {
@ -955,7 +954,7 @@ namespace LC.Newtonsoft.Json.Converters
/// Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produced multiple root elements. /// Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produced multiple root elements.
/// </summary> /// </summary>
/// <value>The name of the deserialized root element.</value> /// <value>The name of the deserialized root element.</value>
public string? DeserializeRootElementName { get; set; } public string DeserializeRootElementName { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value to indicate whether to write the Json.NET array attribute. /// Gets or sets a value to indicate whether to write the Json.NET array attribute.
@ -986,7 +985,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (value == null) if (value == null)
{ {
@ -1032,9 +1031,9 @@ namespace LC.Newtonsoft.Json.Converters
private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager) private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager)
{ {
List<IXmlNode>? parentElements = null; List<IXmlNode> parentElements = null;
IXmlNode? parent = node; IXmlNode parent = node;
while ((parent = parent.ParentNode) != null) while ((parent = parent.ParentNode) != null)
{ {
if (parent.NodeType == XmlNodeType.Element) if (parent.NodeType == XmlNodeType.Element)
@ -1068,11 +1067,11 @@ namespace LC.Newtonsoft.Json.Converters
private string ResolveFullName(IXmlNode node, XmlNamespaceManager manager) private string ResolveFullName(IXmlNode node, XmlNamespaceManager manager)
{ {
string? prefix = (node.NamespaceUri == null || (node.LocalName == "xmlns" && node.NamespaceUri == "http://www.w3.org/2000/xmlns/")) string prefix = (node.NamespaceUri == null || (node.LocalName == "xmlns" && node.NamespaceUri == "http://www.w3.org/2000/xmlns/"))
? null ? null
: manager.LookupPrefix(node.NamespaceUri); : manager.LookupPrefix(node.NamespaceUri);
if (!StringUtils.IsNullOrEmpty(prefix)) if (!string.IsNullOrEmpty(prefix))
{ {
return prefix + ":" + XmlConvert.DecodeName(node.LocalName); return prefix + ":" + XmlConvert.DecodeName(node.LocalName);
} }
@ -1161,9 +1160,9 @@ namespace LC.Newtonsoft.Json.Converters
// value of dictionary will be a single IXmlNode when there is one for a name, // value of dictionary will be a single IXmlNode when there is one for a name,
// or a List<IXmlNode> when there are multiple // or a List<IXmlNode> when there are multiple
Dictionary<string, object>? nodesGroupedByName = null; Dictionary<string, object> nodesGroupedByName = null;
string? nodeName = null; string nodeName = null;
for (int i = 0; i < node.ChildNodes.Count; i++) for (int i = 0; i < node.ChildNodes.Count; i++)
{ {
@ -1209,7 +1208,7 @@ namespace LC.Newtonsoft.Json.Converters
{ {
if (!(value is List<IXmlNode> nodes)) if (!(value is List<IXmlNode> nodes))
{ {
nodes = new List<IXmlNode> {(IXmlNode)value!}; nodes = new List<IXmlNode> {(IXmlNode)value};
nodesGroupedByName[currentNodeName] = nodes; nodesGroupedByName[currentNodeName] = nodes;
} }
@ -1220,7 +1219,7 @@ namespace LC.Newtonsoft.Json.Converters
if (nodesGroupedByName == null) if (nodesGroupedByName == null)
{ {
WriteGroupedNodes(writer, manager, writePropertyName, node.ChildNodes, nodeName!); WriteGroupedNodes(writer, manager, writePropertyName, node.ChildNodes, nodeName);
} }
else else
{ {
@ -1316,11 +1315,7 @@ namespace LC.Newtonsoft.Json.Converters
string namespacePrefix = (attribute.LocalName != "xmlns") string namespacePrefix = (attribute.LocalName != "xmlns")
? XmlConvert.DecodeName(attribute.LocalName) ? XmlConvert.DecodeName(attribute.LocalName)
: string.Empty; : string.Empty;
string? namespaceUri = attribute.Value; string namespaceUri = attribute.Value;
if (namespaceUri == null)
{
throw new JsonSerializationException("Namespace attribute must have a value.");
}
manager.AddNamespace(namespacePrefix, namespaceUri); manager.AddNamespace(namespacePrefix, namespaceUri);
} }
@ -1405,17 +1400,17 @@ namespace LC.Newtonsoft.Json.Converters
writer.WritePropertyName(GetPropertyName(node, manager)); writer.WritePropertyName(GetPropertyName(node, manager));
writer.WriteStartObject(); writer.WriteStartObject();
if (!StringUtils.IsNullOrEmpty(declaration.Version)) if (!string.IsNullOrEmpty(declaration.Version))
{ {
writer.WritePropertyName("@version"); writer.WritePropertyName("@version");
writer.WriteValue(declaration.Version); writer.WriteValue(declaration.Version);
} }
if (!StringUtils.IsNullOrEmpty(declaration.Encoding)) if (!string.IsNullOrEmpty(declaration.Encoding))
{ {
writer.WritePropertyName("@encoding"); writer.WritePropertyName("@encoding");
writer.WriteValue(declaration.Encoding); writer.WriteValue(declaration.Encoding);
} }
if (!StringUtils.IsNullOrEmpty(declaration.Standalone)) if (!string.IsNullOrEmpty(declaration.Standalone))
{ {
writer.WritePropertyName("@standalone"); writer.WritePropertyName("@standalone");
writer.WriteValue(declaration.Standalone); writer.WriteValue(declaration.Standalone);
@ -1428,22 +1423,22 @@ namespace LC.Newtonsoft.Json.Converters
writer.WritePropertyName(GetPropertyName(node, manager)); writer.WritePropertyName(GetPropertyName(node, manager));
writer.WriteStartObject(); writer.WriteStartObject();
if (!StringUtils.IsNullOrEmpty(documentType.Name)) if (!string.IsNullOrEmpty(documentType.Name))
{ {
writer.WritePropertyName("@name"); writer.WritePropertyName("@name");
writer.WriteValue(documentType.Name); writer.WriteValue(documentType.Name);
} }
if (!StringUtils.IsNullOrEmpty(documentType.Public)) if (!string.IsNullOrEmpty(documentType.Public))
{ {
writer.WritePropertyName("@public"); writer.WritePropertyName("@public");
writer.WriteValue(documentType.Public); writer.WriteValue(documentType.Public);
} }
if (!StringUtils.IsNullOrEmpty(documentType.System)) if (!string.IsNullOrEmpty(documentType.System))
{ {
writer.WritePropertyName("@system"); writer.WritePropertyName("@system");
writer.WriteValue(documentType.System); writer.WriteValue(documentType.System);
} }
if (!StringUtils.IsNullOrEmpty(documentType.InternalSubset)) if (!string.IsNullOrEmpty(documentType.InternalSubset))
{ {
writer.WritePropertyName("@internalSubset"); writer.WritePropertyName("@internalSubset");
writer.WriteValue(documentType.InternalSubset); writer.WriteValue(documentType.InternalSubset);
@ -1478,7 +1473,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
switch (reader.TokenType) switch (reader.TokenType)
{ {
@ -1491,8 +1486,8 @@ namespace LC.Newtonsoft.Json.Converters
} }
XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable()); XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
IXmlDocument? document = null; IXmlDocument document = null;
IXmlNode? rootNode = null; IXmlNode rootNode = null;
#if HAVE_XLINQ #if HAVE_XLINQ
if (typeof(XObject).IsAssignableFrom(objectType)) if (typeof(XObject).IsAssignableFrom(objectType))
@ -1537,7 +1532,7 @@ namespace LC.Newtonsoft.Json.Converters
throw JsonSerializationException.Create(reader, "Unexpected type when converting XML: " + objectType); throw JsonSerializationException.Create(reader, "Unexpected type when converting XML: " + objectType);
} }
if (!StringUtils.IsNullOrEmpty(DeserializeRootElementName)) if (!string.IsNullOrEmpty(DeserializeRootElementName))
{ {
ReadElement(reader, document, rootNode, DeserializeRootElementName, manager); ReadElement(reader, document, rootNode, DeserializeRootElementName, manager);
} }
@ -1550,7 +1545,7 @@ namespace LC.Newtonsoft.Json.Converters
#if HAVE_XLINQ #if HAVE_XLINQ
if (objectType == typeof(XElement)) if (objectType == typeof(XElement))
{ {
XElement element = (XElement)document.DocumentElement!.WrappedNode!; XElement element = (XElement)document.DocumentElement.WrappedNode;
element.Remove(); element.Remove();
return element; return element;
@ -1559,7 +1554,7 @@ namespace LC.Newtonsoft.Json.Converters
#if HAVE_XML_DOCUMENT #if HAVE_XML_DOCUMENT
if (objectType == typeof(XmlElement)) if (objectType == typeof(XmlElement))
{ {
return document.DocumentElement!.WrappedNode; return document.DocumentElement.WrappedNode;
} }
#endif #endif
@ -1586,7 +1581,7 @@ namespace LC.Newtonsoft.Json.Converters
return; return;
default: default:
// processing instructions and the xml declaration start with ? // processing instructions and the xml declaration start with ?
if (!StringUtils.IsNullOrEmpty(propertyName) && propertyName[0] == '?') if (!string.IsNullOrEmpty(propertyName) && propertyName[0] == '?')
{ {
CreateInstruction(reader, document, currentNode, propertyName); CreateInstruction(reader, document, currentNode, propertyName);
return; return;
@ -1616,13 +1611,13 @@ namespace LC.Newtonsoft.Json.Converters
private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager) private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager)
{ {
if (StringUtils.IsNullOrEmpty(propertyName)) if (string.IsNullOrEmpty(propertyName))
{ {
throw JsonSerializationException.Create(reader, "XmlNodeConverter cannot convert JSON with an empty property name to XML."); throw JsonSerializationException.Create(reader, "XmlNodeConverter cannot convert JSON with an empty property name to XML.");
} }
Dictionary<string, string?>? attributeNameValues = null; Dictionary<string, string> attributeNameValues = null;
string? elementPrefix = null; string elementPrefix = null;
if (!EncodeSpecialCharacters) if (!EncodeSpecialCharacters)
{ {
@ -1634,7 +1629,7 @@ namespace LC.Newtonsoft.Json.Converters
if (propertyName.StartsWith('@')) if (propertyName.StartsWith('@'))
{ {
string attributeName = propertyName.Substring(1); string attributeName = propertyName.Substring(1);
string? attributePrefix = MiscellaneousUtils.GetPrefix(attributeName); string attributePrefix = MiscellaneousUtils.GetPrefix(attributeName);
AddAttribute(reader, document, currentNode, propertyName, attributeName, manager, attributePrefix); AddAttribute(reader, document, currentNode, propertyName, attributeName, manager, attributePrefix);
return; return;
@ -1671,7 +1666,7 @@ namespace LC.Newtonsoft.Json.Converters
CreateElement(reader, document, currentNode, propertyName, manager, elementPrefix, attributeNameValues); CreateElement(reader, document, currentNode, propertyName, manager, elementPrefix, attributeNameValues);
} }
private void CreateElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string elementName, XmlNamespaceManager manager, string? elementPrefix, Dictionary<string, string?>? attributeNameValues) private void CreateElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string elementName, XmlNamespaceManager manager, string elementPrefix, Dictionary<string, string> attributeNameValues)
{ {
IXmlElement element = CreateElement(elementName, document, elementPrefix, manager); IXmlElement element = CreateElement(elementName, document, elementPrefix, manager);
@ -1680,12 +1675,12 @@ namespace LC.Newtonsoft.Json.Converters
if (attributeNameValues != null) if (attributeNameValues != null)
{ {
// add attributes to newly created element // add attributes to newly created element
foreach (KeyValuePair<string, string?> nameValue in attributeNameValues) foreach (KeyValuePair<string, string> nameValue in attributeNameValues)
{ {
string encodedName = XmlConvert.EncodeName(nameValue.Key); string encodedName = XmlConvert.EncodeName(nameValue.Key);
string? attributePrefix = MiscellaneousUtils.GetPrefix(nameValue.Key); string attributePrefix = MiscellaneousUtils.GetPrefix(nameValue.Key);
IXmlNode attribute = (!StringUtils.IsNullOrEmpty(attributePrefix)) ? document.CreateAttribute(encodedName, manager.LookupNamespace(attributePrefix) ?? string.Empty, nameValue.Value) : document.CreateAttribute(encodedName, nameValue.Value); IXmlNode attribute = (!string.IsNullOrEmpty(attributePrefix)) ? document.CreateAttribute(encodedName, manager.LookupNamespace(attributePrefix) ?? string.Empty, nameValue.Value) : document.CreateAttribute(encodedName, nameValue.Value);
element.SetAttributeNode(attribute); element.SetAttributeNode(attribute);
} }
@ -1699,7 +1694,7 @@ namespace LC.Newtonsoft.Json.Converters
case JsonToken.Boolean: case JsonToken.Boolean:
case JsonToken.Date: case JsonToken.Date:
case JsonToken.Bytes: case JsonToken.Bytes:
string? text = ConvertTokenToXmlValue(reader); string text = ConvertTokenToXmlValue(reader);
if (text != null) if (text != null)
{ {
element.AppendChild(document.CreateTextNode(text)); element.AppendChild(document.CreateTextNode(text));
@ -1723,7 +1718,7 @@ namespace LC.Newtonsoft.Json.Converters
} }
} }
private static void AddAttribute(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, string attributeName, XmlNamespaceManager manager, string? attributePrefix) private static void AddAttribute(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, string attributeName, XmlNamespaceManager manager, string attributePrefix)
{ {
if (currentNode.NodeType == XmlNodeType.Document) if (currentNode.NodeType == XmlNodeType.Document)
{ {
@ -1731,16 +1726,16 @@ namespace LC.Newtonsoft.Json.Converters
} }
string encodedName = XmlConvert.EncodeName(attributeName); string encodedName = XmlConvert.EncodeName(attributeName);
string? attributeValue = ConvertTokenToXmlValue(reader); string attributeValue = ConvertTokenToXmlValue(reader);
IXmlNode attribute = (!StringUtils.IsNullOrEmpty(attributePrefix)) IXmlNode attribute = (!string.IsNullOrEmpty(attributePrefix))
? document.CreateAttribute(encodedName, manager.LookupNamespace(attributePrefix), attributeValue) ? document.CreateAttribute(encodedName, manager.LookupNamespace(attributePrefix), attributeValue)
: document.CreateAttribute(encodedName, attributeValue); : document.CreateAttribute(encodedName, attributeValue);
((IXmlElement)currentNode).SetAttributeNode(attribute); ((IXmlElement)currentNode).SetAttributeNode(attribute);
} }
private static string? ConvertTokenToXmlValue(JsonReader reader) private static string ConvertTokenToXmlValue(JsonReader reader)
{ {
switch (reader.TokenType) switch (reader.TokenType)
{ {
@ -1787,7 +1782,7 @@ namespace LC.Newtonsoft.Json.Converters
#endif #endif
} }
case JsonToken.Bytes: case JsonToken.Bytes:
return Convert.ToBase64String((byte[])reader.Value!); return Convert.ToBase64String((byte[])reader.Value);
case JsonToken.Null: case JsonToken.Null:
return null; return null;
default: default:
@ -1797,7 +1792,7 @@ namespace LC.Newtonsoft.Json.Converters
private void ReadArrayElements(JsonReader reader, IXmlDocument document, string propertyName, IXmlNode currentNode, XmlNamespaceManager manager) private void ReadArrayElements(JsonReader reader, IXmlDocument document, string propertyName, IXmlNode currentNode, XmlNamespaceManager manager)
{ {
string? elementPrefix = MiscellaneousUtils.GetPrefix(propertyName); string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
IXmlElement nestedArrayElement = CreateElement(propertyName, document, elementPrefix, manager); IXmlElement nestedArrayElement = CreateElement(propertyName, document, elementPrefix, manager);
@ -1863,9 +1858,9 @@ namespace LC.Newtonsoft.Json.Converters
return true; return true;
} }
private Dictionary<string, string?>? ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager) private Dictionary<string, string> ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager)
{ {
Dictionary<string, string?>? attributeNameValues = null; Dictionary<string, string> attributeNameValues = null;
bool finished = false; bool finished = false;
// read properties until first non-attribute is encountered // read properties until first non-attribute is encountered
@ -1874,19 +1869,19 @@ namespace LC.Newtonsoft.Json.Converters
switch (reader.TokenType) switch (reader.TokenType)
{ {
case JsonToken.PropertyName: case JsonToken.PropertyName:
string attributeName = reader.Value!.ToString(); string attributeName = reader.Value.ToString();
if (!StringUtils.IsNullOrEmpty(attributeName)) if (!string.IsNullOrEmpty(attributeName))
{ {
char firstChar = attributeName[0]; char firstChar = attributeName[0];
string? attributeValue; string attributeValue;
switch (firstChar) switch (firstChar)
{ {
case '@': case '@':
if (attributeNameValues == null) if (attributeNameValues == null)
{ {
attributeNameValues = new Dictionary<string, string?>(); attributeNameValues = new Dictionary<string, string>();
} }
attributeName = attributeName.Substring(1); attributeName = attributeName.Substring(1);
@ -1894,7 +1889,7 @@ namespace LC.Newtonsoft.Json.Converters
attributeValue = ConvertTokenToXmlValue(reader); attributeValue = ConvertTokenToXmlValue(reader);
attributeNameValues.Add(attributeName, attributeValue); attributeNameValues.Add(attributeName, attributeValue);
if (IsNamespaceAttribute(attributeName, out string? namespacePrefix)) if (IsNamespaceAttribute(attributeName, out string namespacePrefix))
{ {
manager.AddNamespace(namespacePrefix, attributeValue); manager.AddNamespace(namespacePrefix, attributeValue);
} }
@ -1914,7 +1909,7 @@ namespace LC.Newtonsoft.Json.Converters
{ {
if (attributeNameValues == null) if (attributeNameValues == null)
{ {
attributeNameValues = new Dictionary<string, string?>(); attributeNameValues = new Dictionary<string, string>();
} }
// ensure that the prefix used is free // ensure that the prefix used is free
@ -1946,7 +1941,7 @@ namespace LC.Newtonsoft.Json.Converters
if (attributeNameValues == null) if (attributeNameValues == null)
{ {
attributeNameValues = new Dictionary<string, string?>(); attributeNameValues = new Dictionary<string, string>();
} }
attributeValue = reader.Value?.ToString(); attributeValue = reader.Value?.ToString();
@ -1984,12 +1979,12 @@ namespace LC.Newtonsoft.Json.Converters
{ {
if (propertyName == DeclarationName) if (propertyName == DeclarationName)
{ {
string? version = null; string version = null;
string? encoding = null; string encoding = null;
string? standalone = null; string standalone = null;
while (reader.Read() && reader.TokenType != JsonToken.EndObject) while (reader.Read() && reader.TokenType != JsonToken.EndObject)
{ {
switch (reader.Value?.ToString()) switch (reader.Value.ToString())
{ {
case "@version": case "@version":
reader.ReadAndAssert(); reader.ReadAndAssert();
@ -2021,13 +2016,13 @@ namespace LC.Newtonsoft.Json.Converters
#if HAVE_XML_DOCUMENT_TYPE #if HAVE_XML_DOCUMENT_TYPE
private void CreateDocumentType(JsonReader reader, IXmlDocument document, IXmlNode currentNode) private void CreateDocumentType(JsonReader reader, IXmlDocument document, IXmlNode currentNode)
{ {
string? name = null; string name = null;
string? publicId = null; string publicId = null;
string? systemId = null; string systemId = null;
string? internalSubset = null; string internalSubset = null;
while (reader.Read() && reader.TokenType != JsonToken.EndObject) while (reader.Read() && reader.TokenType != JsonToken.EndObject)
{ {
switch (reader.Value?.ToString()) switch (reader.Value.ToString())
{ {
case "@name": case "@name":
reader.ReadAndAssert(); reader.ReadAndAssert();
@ -2055,12 +2050,12 @@ namespace LC.Newtonsoft.Json.Converters
} }
#endif #endif
private IXmlElement CreateElement(string elementName, IXmlDocument document, string? elementPrefix, XmlNamespaceManager manager) private IXmlElement CreateElement(string elementName, IXmlDocument document, string elementPrefix, XmlNamespaceManager manager)
{ {
string encodeName = EncodeSpecialCharacters ? XmlConvert.EncodeLocalName(elementName) : XmlConvert.EncodeName(elementName); string encodeName = EncodeSpecialCharacters ? XmlConvert.EncodeLocalName(elementName) : XmlConvert.EncodeName(elementName);
string ns = StringUtils.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix); string ns = string.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix);
IXmlElement element = (!StringUtils.IsNullOrEmpty(ns)) ? document.CreateElement(encodeName, ns) : document.CreateElement(encodeName); IXmlElement element = (!string.IsNullOrEmpty(ns)) ? document.CreateElement(encodeName, ns) : document.CreateElement(encodeName);
return element; return element;
} }
@ -2077,7 +2072,7 @@ namespace LC.Newtonsoft.Json.Converters
throw JsonSerializationException.Create(reader, "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName."); throw JsonSerializationException.Create(reader, "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName.");
} }
string propertyName = reader.Value!.ToString(); string propertyName = reader.Value.ToString();
reader.ReadAndAssert(); reader.ReadAndAssert();
if (reader.TokenType == JsonToken.StartArray) if (reader.TokenType == JsonToken.StartArray)
@ -2091,8 +2086,8 @@ namespace LC.Newtonsoft.Json.Converters
if (count == 1 && WriteArrayAttribute) if (count == 1 && WriteArrayAttribute)
{ {
MiscellaneousUtils.GetQualifiedNameParts(propertyName, out string? elementPrefix, out string localName); MiscellaneousUtils.GetQualifiedNameParts(propertyName, out string elementPrefix, out string localName);
string ns = StringUtils.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix); string ns = string.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix);
foreach (IXmlNode childNode in currentNode.ChildNodes) foreach (IXmlNode childNode in currentNode.ChildNodes)
{ {
@ -2110,7 +2105,7 @@ namespace LC.Newtonsoft.Json.Converters
} }
continue; continue;
case JsonToken.StartConstructor: case JsonToken.StartConstructor:
string constructorName = reader.Value!.ToString(); string constructorName = reader.Value.ToString();
while (reader.Read() && reader.TokenType != JsonToken.EndConstructor) while (reader.Read() && reader.TokenType != JsonToken.EndConstructor)
{ {
@ -2118,7 +2113,7 @@ namespace LC.Newtonsoft.Json.Converters
} }
break; break;
case JsonToken.Comment: case JsonToken.Comment:
currentNode.AppendChild(document.CreateComment((string)reader.Value!)); currentNode.AppendChild(document.CreateComment((string)reader.Value));
break; break;
case JsonToken.EndObject: case JsonToken.EndObject:
case JsonToken.EndArray: case JsonToken.EndArray:
@ -2136,7 +2131,7 @@ namespace LC.Newtonsoft.Json.Converters
/// <param name="attributeName">Attribute name to test.</param> /// <param name="attributeName">Attribute name to test.</param>
/// <param name="prefix">The attribute name prefix if it has one, otherwise an empty string.</param> /// <param name="prefix">The attribute name prefix if it has one, otherwise an empty string.</param>
/// <returns><c>true</c> if attribute name is for a namespace attribute, otherwise <c>false</c>.</returns> /// <returns><c>true</c> if attribute name is for a namespace attribute, otherwise <c>false</c>.</returns>
private bool IsNamespaceAttribute(string attributeName, [NotNullWhen(true)]out string? prefix) private bool IsNamespaceAttribute(string attributeName, out string prefix)
{ {
if (attributeName.StartsWith("xmlns", StringComparison.Ordinal)) if (attributeName.StartsWith("xmlns", StringComparison.Ordinal))
{ {

View File

@ -36,14 +36,14 @@ namespace LC.Newtonsoft.Json
None = 0, None = 0,
/// <summary> /// <summary>
/// Date formatted strings, e.g. <c>"\/Date(1198908717056)\/"</c> and <c>"2012-03-21T05:40Z"</c>, are parsed to <see cref="System.DateTime"/>. /// Date formatted strings, e.g. <c>"\/Date(1198908717056)\/"</c> and <c>"2012-03-21T05:40Z"</c>, are parsed to <see cref="DateTime"/>.
/// </summary> /// </summary>
DateTime = 1, DateTime = 1,
#if HAVE_DATE_TIME_OFFSET #if HAVE_DATE_TIME_OFFSET
/// <summary> /// <summary>
/// Date formatted strings, e.g. <c>"\/Date(1198908717056)\/"</c> and <c>"2012-03-21T05:40Z"</c>, are parsed to <see cref="System.DateTimeOffset"/>. /// Date formatted strings, e.g. <c>"\/Date(1198908717056)\/"</c> and <c>"2012-03-21T05:40Z"</c>, are parsed to <see cref="DateTimeOffset"/>.
/// </summary> /// </summary>
DateTimeOffset = 2 DateTimeOffset = 2
#endif #endif
} }
} }

View File

@ -59,7 +59,7 @@ namespace LC.Newtonsoft.Json
/// <param name="start">The zero-based index into the array specifying the first character of the name.</param> /// <param name="start">The zero-based index into the array specifying the first character of the name.</param>
/// <param name="length">The number of characters in the name.</param> /// <param name="length">The number of characters in the name.</param>
/// <returns>A string containing the same characters as the specified range of characters in the given array.</returns> /// <returns>A string containing the same characters as the specified range of characters in the given array.</returns>
public override string? Get(char[] key, int start, int length) public override string Get(char[] key, int start, int length)
{ {
if (length == 0) if (length == 0)
{ {

View File

@ -17,6 +17,6 @@
/// Return an array to the pool. /// Return an array to the pool.
/// </summary> /// </summary>
/// <param name="array">The array that is being returned.</param> /// <param name="array">The array that is being returned.</param>
void Return(T[]? array); void Return(T[] array);
} }
} }

View File

@ -38,25 +38,25 @@ namespace LC.Newtonsoft.Json
/// Gets or sets the id. /// Gets or sets the id.
/// </summary> /// </summary>
/// <value>The id.</value> /// <value>The id.</value>
public string? Id { get; set; } public string Id { get; set; }
/// <summary> /// <summary>
/// Gets or sets the title. /// Gets or sets the title.
/// </summary> /// </summary>
/// <value>The title.</value> /// <value>The title.</value>
public string? Title { get; set; } public string Title { get; set; }
/// <summary> /// <summary>
/// Gets or sets the description. /// Gets or sets the description.
/// </summary> /// </summary>
/// <value>The description.</value> /// <value>The description.</value>
public string? Description { get; set; } public string Description { get; set; }
/// <summary> /// <summary>
/// Gets or sets the collection's items converter. /// Gets or sets the collection's items converter.
/// </summary> /// </summary>
/// <value>The collection's items converter.</value> /// <value>The collection's items converter.</value>
public Type? ItemConverterType { get; set; } public Type ItemConverterType { get; set; }
/// <summary> /// <summary>
/// The parameter list to use when constructing the <see cref="JsonConverter"/> described by <see cref="ItemConverterType"/>. /// The parameter list to use when constructing the <see cref="JsonConverter"/> described by <see cref="ItemConverterType"/>.
@ -69,13 +69,13 @@ namespace LC.Newtonsoft.Json
/// [JsonContainer(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })] /// [JsonContainer(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })]
/// </code> /// </code>
/// </example> /// </example>
public object[]? ItemConverterParameters { get; set; } public object[] ItemConverterParameters { get; set; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="Type"/> of the <see cref="NamingStrategy"/>. /// Gets or sets the <see cref="Type"/> of the <see cref="NamingStrategy"/>.
/// </summary> /// </summary>
/// <value>The <see cref="Type"/> of the <see cref="NamingStrategy"/>.</value> /// <value>The <see cref="Type"/> of the <see cref="NamingStrategy"/>.</value>
public Type? NamingStrategyType public Type NamingStrategyType
{ {
get => _namingStrategyType; get => _namingStrategyType;
set set
@ -96,7 +96,7 @@ namespace LC.Newtonsoft.Json
/// [JsonContainer(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })] /// [JsonContainer(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })]
/// </code> /// </code>
/// </example> /// </example>
public object[]? NamingStrategyParameters public object[] NamingStrategyParameters
{ {
get => _namingStrategyParameters; get => _namingStrategyParameters;
set set
@ -106,7 +106,7 @@ namespace LC.Newtonsoft.Json
} }
} }
internal NamingStrategy? NamingStrategyInstance { get; set; } internal NamingStrategy NamingStrategyInstance { get; set; }
// yuck. can't set nullable properties on an attribute in C# // yuck. can't set nullable properties on an attribute in C#
// have to use this approach to get an unset default state // have to use this approach to get an unset default state
@ -114,8 +114,8 @@ namespace LC.Newtonsoft.Json
internal bool? _itemIsReference; internal bool? _itemIsReference;
internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal ReferenceLoopHandling? _itemReferenceLoopHandling;
internal TypeNameHandling? _itemTypeNameHandling; internal TypeNameHandling? _itemTypeNameHandling;
private Type? _namingStrategyType; private Type _namingStrategyType;
private object[]? _namingStrategyParameters; private object[] _namingStrategyParameters;
/// <summary> /// <summary>
/// Gets or sets a value that indicates whether to preserve object references. /// Gets or sets a value that indicates whether to preserve object references.

View File

@ -36,10 +36,9 @@ using LC.Newtonsoft.Json.Converters;
using LC.Newtonsoft.Json.Serialization; using LC.Newtonsoft.Json.Serialization;
using System.Text; using System.Text;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Diagnostics.CodeAnalysis;
#if HAVE_XLINQ #if HAVE_XLINQ
using System.Xml.Linq; using System.Xml.Linq;
#endif #endif
namespace LC.Newtonsoft.Json namespace LC.Newtonsoft.Json
@ -59,7 +58,7 @@ namespace LC.Newtonsoft.Json
/// To serialize without using any default settings create a <see cref="JsonSerializer"/> with /// To serialize without using any default settings create a <see cref="JsonSerializer"/> with
/// <see cref="JsonSerializer.Create()"/>. /// <see cref="JsonSerializer.Create()"/>.
/// </summary> /// </summary>
public static Func<JsonSerializerSettings>? DefaultSettings { get; set; } public static Func<JsonSerializerSettings> DefaultSettings { get; set; }
/// <summary> /// <summary>
/// Represents JavaScript's boolean value <c>true</c> as a string. This field is read-only. /// Represents JavaScript's boolean value <c>true</c> as a string. This field is read-only.
@ -396,7 +395,7 @@ namespace LC.Newtonsoft.Json
/// </summary> /// </summary>
/// <param name="value">The value to convert.</param> /// <param name="value">The value to convert.</param>
/// <returns>A JSON string representation of the <see cref="Uri"/>.</returns> /// <returns>A JSON string representation of the <see cref="Uri"/>.</returns>
public static string ToString(Uri? value) public static string ToString(Uri value)
{ {
if (value == null) if (value == null)
{ {
@ -416,7 +415,7 @@ namespace LC.Newtonsoft.Json
/// </summary> /// </summary>
/// <param name="value">The value to convert.</param> /// <param name="value">The value to convert.</param>
/// <returns>A JSON string representation of the <see cref="String"/>.</returns> /// <returns>A JSON string representation of the <see cref="String"/>.</returns>
public static string ToString(string? value) public static string ToString(string value)
{ {
return ToString(value, '"'); return ToString(value, '"');
} }
@ -427,7 +426,7 @@ namespace LC.Newtonsoft.Json
/// <param name="value">The value to convert.</param> /// <param name="value">The value to convert.</param>
/// <param name="delimiter">The string delimiter character.</param> /// <param name="delimiter">The string delimiter character.</param>
/// <returns>A JSON string representation of the <see cref="String"/>.</returns> /// <returns>A JSON string representation of the <see cref="String"/>.</returns>
public static string ToString(string? value, char delimiter) public static string ToString(string value, char delimiter)
{ {
return ToString(value, delimiter, StringEscapeHandling.Default); return ToString(value, delimiter, StringEscapeHandling.Default);
} }
@ -439,7 +438,7 @@ namespace LC.Newtonsoft.Json
/// <param name="delimiter">The string delimiter character.</param> /// <param name="delimiter">The string delimiter character.</param>
/// <param name="stringEscapeHandling">The string escape handling.</param> /// <param name="stringEscapeHandling">The string escape handling.</param>
/// <returns>A JSON string representation of the <see cref="String"/>.</returns> /// <returns>A JSON string representation of the <see cref="String"/>.</returns>
public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling) public static string ToString(string value, char delimiter, StringEscapeHandling stringEscapeHandling)
{ {
if (delimiter != '"' && delimiter != '\'') if (delimiter != '"' && delimiter != '\'')
{ {
@ -454,7 +453,7 @@ namespace LC.Newtonsoft.Json
/// </summary> /// </summary>
/// <param name="value">The value to convert.</param> /// <param name="value">The value to convert.</param>
/// <returns>A JSON string representation of the <see cref="Object"/>.</returns> /// <returns>A JSON string representation of the <see cref="Object"/>.</returns>
public static string ToString(object? value) public static string ToString(object value)
{ {
if (value == null) if (value == null)
{ {
@ -525,9 +524,9 @@ namespace LC.Newtonsoft.Json
/// <param name="value">The object to serialize.</param> /// <param name="value">The object to serialize.</param>
/// <returns>A JSON string representation of the object.</returns> /// <returns>A JSON string representation of the object.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static string SerializeObject(object? value) public static string SerializeObject(object value)
{ {
return SerializeObject(value, null, (JsonSerializerSettings?)null); return SerializeObject(value, null, (JsonSerializerSettings)null);
} }
/// <summary> /// <summary>
@ -539,9 +538,9 @@ namespace LC.Newtonsoft.Json
/// A JSON string representation of the object. /// A JSON string representation of the object.
/// </returns> /// </returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static string SerializeObject(object? value, Formatting formatting) public static string SerializeObject(object value, Formatting formatting)
{ {
return SerializeObject(value, formatting, (JsonSerializerSettings?)null); return SerializeObject(value, formatting, (JsonSerializerSettings)null);
} }
/// <summary> /// <summary>
@ -551,9 +550,9 @@ namespace LC.Newtonsoft.Json
/// <param name="converters">A collection of converters used while serializing.</param> /// <param name="converters">A collection of converters used while serializing.</param>
/// <returns>A JSON string representation of the object.</returns> /// <returns>A JSON string representation of the object.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static string SerializeObject(object? value, params JsonConverter[] converters) public static string SerializeObject(object value, params JsonConverter[] converters)
{ {
JsonSerializerSettings? settings = (converters != null && converters.Length > 0) JsonSerializerSettings settings = (converters != null && converters.Length > 0)
? new JsonSerializerSettings { Converters = converters } ? new JsonSerializerSettings { Converters = converters }
: null; : null;
@ -568,9 +567,9 @@ namespace LC.Newtonsoft.Json
/// <param name="converters">A collection of converters used while serializing.</param> /// <param name="converters">A collection of converters used while serializing.</param>
/// <returns>A JSON string representation of the object.</returns> /// <returns>A JSON string representation of the object.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters) public static string SerializeObject(object value, Formatting formatting, params JsonConverter[] converters)
{ {
JsonSerializerSettings? settings = (converters != null && converters.Length > 0) JsonSerializerSettings settings = (converters != null && converters.Length > 0)
? new JsonSerializerSettings { Converters = converters } ? new JsonSerializerSettings { Converters = converters }
: null; : null;
@ -587,7 +586,7 @@ namespace LC.Newtonsoft.Json
/// A JSON string representation of the object. /// A JSON string representation of the object.
/// </returns> /// </returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static string SerializeObject(object? value, JsonSerializerSettings? settings) public static string SerializeObject(object value, JsonSerializerSettings settings)
{ {
return SerializeObject(value, null, settings); return SerializeObject(value, null, settings);
} }
@ -607,7 +606,7 @@ namespace LC.Newtonsoft.Json
/// A JSON string representation of the object. /// A JSON string representation of the object.
/// </returns> /// </returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings) public static string SerializeObject(object value, Type type, JsonSerializerSettings settings)
{ {
JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
@ -625,7 +624,7 @@ namespace LC.Newtonsoft.Json
/// A JSON string representation of the object. /// A JSON string representation of the object.
/// </returns> /// </returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings) public static string SerializeObject(object value, Formatting formatting, JsonSerializerSettings settings)
{ {
return SerializeObject(value, null, formatting, settings); return SerializeObject(value, null, formatting, settings);
} }
@ -646,7 +645,7 @@ namespace LC.Newtonsoft.Json
/// A JSON string representation of the object. /// A JSON string representation of the object.
/// </returns> /// </returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings) public static string SerializeObject(object value, Type type, Formatting formatting, JsonSerializerSettings settings)
{ {
JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
jsonSerializer.Formatting = formatting; jsonSerializer.Formatting = formatting;
@ -654,7 +653,7 @@ namespace LC.Newtonsoft.Json
return SerializeObjectInternal(value, type, jsonSerializer); return SerializeObjectInternal(value, type, jsonSerializer);
} }
private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer) private static string SerializeObjectInternal(object value, Type type, JsonSerializer jsonSerializer)
{ {
StringBuilder sb = new StringBuilder(256); StringBuilder sb = new StringBuilder(256);
StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture); StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture);
@ -676,9 +675,9 @@ namespace LC.Newtonsoft.Json
/// <param name="value">The JSON to deserialize.</param> /// <param name="value">The JSON to deserialize.</param>
/// <returns>The deserialized object from the JSON string.</returns> /// <returns>The deserialized object from the JSON string.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static object? DeserializeObject(string value) public static object DeserializeObject(string value)
{ {
return DeserializeObject(value, null, (JsonSerializerSettings?)null); return DeserializeObject(value, null, (JsonSerializerSettings)null);
} }
/// <summary> /// <summary>
@ -691,7 +690,7 @@ namespace LC.Newtonsoft.Json
/// </param> /// </param>
/// <returns>The deserialized object from the JSON string.</returns> /// <returns>The deserialized object from the JSON string.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static object? DeserializeObject(string value, JsonSerializerSettings settings) public static object DeserializeObject(string value, JsonSerializerSettings settings)
{ {
return DeserializeObject(value, null, settings); return DeserializeObject(value, null, settings);
} }
@ -703,9 +702,9 @@ namespace LC.Newtonsoft.Json
/// <param name="type">The <see cref="Type"/> of object being deserialized.</param> /// <param name="type">The <see cref="Type"/> of object being deserialized.</param>
/// <returns>The deserialized object from the JSON string.</returns> /// <returns>The deserialized object from the JSON string.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static object? DeserializeObject(string value, Type type) public static object DeserializeObject(string value, Type type)
{ {
return DeserializeObject(value, type, (JsonSerializerSettings?)null); return DeserializeObject(value, type, (JsonSerializerSettings)null);
} }
/// <summary> /// <summary>
@ -715,9 +714,9 @@ namespace LC.Newtonsoft.Json
/// <param name="value">The JSON to deserialize.</param> /// <param name="value">The JSON to deserialize.</param>
/// <returns>The deserialized object from the JSON string.</returns> /// <returns>The deserialized object from the JSON string.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static T? DeserializeObject<T>(string value) public static T DeserializeObject<T>(string value)
{ {
return DeserializeObject<T>(value, (JsonSerializerSettings?)null); return DeserializeObject<T>(value, (JsonSerializerSettings)null);
} }
/// <summary> /// <summary>
@ -732,7 +731,7 @@ namespace LC.Newtonsoft.Json
/// <param name="anonymousTypeObject">The anonymous type object.</param> /// <param name="anonymousTypeObject">The anonymous type object.</param>
/// <returns>The deserialized anonymous type from the JSON string.</returns> /// <returns>The deserialized anonymous type from the JSON string.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject) public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
{ {
return DeserializeObject<T>(value); return DeserializeObject<T>(value);
} }
@ -753,7 +752,7 @@ namespace LC.Newtonsoft.Json
/// </param> /// </param>
/// <returns>The deserialized anonymous type from the JSON string.</returns> /// <returns>The deserialized anonymous type from the JSON string.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings) public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings)
{ {
return DeserializeObject<T>(value, settings); return DeserializeObject<T>(value, settings);
} }
@ -766,9 +765,9 @@ namespace LC.Newtonsoft.Json
/// <param name="converters">Converters to use while deserializing.</param> /// <param name="converters">Converters to use while deserializing.</param>
/// <returns>The deserialized object from the JSON string.</returns> /// <returns>The deserialized object from the JSON string.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static T? DeserializeObject<T>(string value, params JsonConverter[] converters) public static T DeserializeObject<T>(string value, params JsonConverter[] converters)
{ {
return (T?)DeserializeObject(value, typeof(T), converters); return (T)DeserializeObject(value, typeof(T), converters);
} }
/// <summary> /// <summary>
@ -782,9 +781,9 @@ namespace LC.Newtonsoft.Json
/// </param> /// </param>
/// <returns>The deserialized object from the JSON string.</returns> /// <returns>The deserialized object from the JSON string.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static T? DeserializeObject<T>(string value, JsonSerializerSettings? settings) public static T DeserializeObject<T>(string value, JsonSerializerSettings settings)
{ {
return (T?)DeserializeObject(value, typeof(T), settings); return (T)DeserializeObject(value, typeof(T), settings);
} }
/// <summary> /// <summary>
@ -795,9 +794,9 @@ namespace LC.Newtonsoft.Json
/// <param name="converters">Converters to use while deserializing.</param> /// <param name="converters">Converters to use while deserializing.</param>
/// <returns>The deserialized object from the JSON string.</returns> /// <returns>The deserialized object from the JSON string.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters) public static object DeserializeObject(string value, Type type, params JsonConverter[] converters)
{ {
JsonSerializerSettings? settings = (converters != null && converters.Length > 0) JsonSerializerSettings settings = (converters != null && converters.Length > 0)
? new JsonSerializerSettings { Converters = converters } ? new JsonSerializerSettings { Converters = converters }
: null; : null;
@ -814,7 +813,7 @@ namespace LC.Newtonsoft.Json
/// If this is <c>null</c>, default serialization settings will be used. /// If this is <c>null</c>, default serialization settings will be used.
/// </param> /// </param>
/// <returns>The deserialized object from the JSON string.</returns> /// <returns>The deserialized object from the JSON string.</returns>
public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings) public static object DeserializeObject(string value, Type type, JsonSerializerSettings settings)
{ {
ValidationUtils.ArgumentNotNull(value, nameof(value)); ValidationUtils.ArgumentNotNull(value, nameof(value));
@ -854,7 +853,7 @@ namespace LC.Newtonsoft.Json
/// The <see cref="JsonSerializerSettings"/> used to deserialize the object. /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
/// If this is <c>null</c>, default serialization settings will be used. /// If this is <c>null</c>, default serialization settings will be used.
/// </param> /// </param>
public static void PopulateObject(string value, object target, JsonSerializerSettings? settings) public static void PopulateObject(string value, object target, JsonSerializerSettings settings)
{ {
JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
@ -883,7 +882,7 @@ namespace LC.Newtonsoft.Json
/// </summary> /// </summary>
/// <param name="node">The node to serialize.</param> /// <param name="node">The node to serialize.</param>
/// <returns>A JSON string of the <see cref="XmlNode"/>.</returns> /// <returns>A JSON string of the <see cref="XmlNode"/>.</returns>
public static string SerializeXmlNode(XmlNode? node) public static string SerializeXmlNode(XmlNode node)
{ {
return SerializeXmlNode(node, Formatting.None); return SerializeXmlNode(node, Formatting.None);
} }
@ -894,7 +893,7 @@ namespace LC.Newtonsoft.Json
/// <param name="node">The node to serialize.</param> /// <param name="node">The node to serialize.</param>
/// <param name="formatting">Indicates how the output should be formatted.</param> /// <param name="formatting">Indicates how the output should be formatted.</param>
/// <returns>A JSON string of the <see cref="XmlNode"/>.</returns> /// <returns>A JSON string of the <see cref="XmlNode"/>.</returns>
public static string SerializeXmlNode(XmlNode? node, Formatting formatting) public static string SerializeXmlNode(XmlNode node, Formatting formatting)
{ {
XmlNodeConverter converter = new XmlNodeConverter(); XmlNodeConverter converter = new XmlNodeConverter();
@ -908,7 +907,7 @@ namespace LC.Newtonsoft.Json
/// <param name="formatting">Indicates how the output should be formatted.</param> /// <param name="formatting">Indicates how the output should be formatted.</param>
/// <param name="omitRootObject">Omits writing the root object.</param> /// <param name="omitRootObject">Omits writing the root object.</param>
/// <returns>A JSON string of the <see cref="XmlNode"/>.</returns> /// <returns>A JSON string of the <see cref="XmlNode"/>.</returns>
public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject) public static string SerializeXmlNode(XmlNode node, Formatting formatting, bool omitRootObject)
{ {
XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject }; XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject };
@ -920,7 +919,7 @@ namespace LC.Newtonsoft.Json
/// </summary> /// </summary>
/// <param name="value">The JSON string.</param> /// <param name="value">The JSON string.</param>
/// <returns>The deserialized <see cref="XmlNode"/>.</returns> /// <returns>The deserialized <see cref="XmlNode"/>.</returns>
public static XmlDocument? DeserializeXmlNode(string value) public static XmlDocument DeserializeXmlNode(string value)
{ {
return DeserializeXmlNode(value, null); return DeserializeXmlNode(value, null);
} }
@ -931,7 +930,7 @@ namespace LC.Newtonsoft.Json
/// <param name="value">The JSON string.</param> /// <param name="value">The JSON string.</param>
/// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param> /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
/// <returns>The deserialized <see cref="XmlNode"/>.</returns> /// <returns>The deserialized <see cref="XmlNode"/>.</returns>
public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName) public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName)
{ {
return DeserializeXmlNode(value, deserializeRootElementName, false); return DeserializeXmlNode(value, deserializeRootElementName, false);
} }
@ -947,7 +946,7 @@ namespace LC.Newtonsoft.Json
/// This attribute helps preserve arrays when converting the written XML back to JSON. /// This attribute helps preserve arrays when converting the written XML back to JSON.
/// </param> /// </param>
/// <returns>The deserialized <see cref="XmlNode"/>.</returns> /// <returns>The deserialized <see cref="XmlNode"/>.</returns>
public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName, bool writeArrayAttribute)
{ {
return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, false); return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, false);
} }
@ -969,14 +968,14 @@ namespace LC.Newtonsoft.Json
/// as part of the XML element name. /// as part of the XML element name.
/// </param> /// </param>
/// <returns>The deserialized <see cref="XmlNode"/>.</returns> /// <returns>The deserialized <see cref="XmlNode"/>.</returns>
public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters)
{ {
XmlNodeConverter converter = new XmlNodeConverter(); XmlNodeConverter converter = new XmlNodeConverter();
converter.DeserializeRootElementName = deserializeRootElementName; converter.DeserializeRootElementName = deserializeRootElementName;
converter.WriteArrayAttribute = writeArrayAttribute; converter.WriteArrayAttribute = writeArrayAttribute;
converter.EncodeSpecialCharacters = encodeSpecialCharacters; converter.EncodeSpecialCharacters = encodeSpecialCharacters;
return (XmlDocument?)DeserializeObject(value, typeof(XmlDocument), converter); return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), converter);
} }
#endif #endif
@ -986,7 +985,7 @@ namespace LC.Newtonsoft.Json
/// </summary> /// </summary>
/// <param name="node">The node to convert to JSON.</param> /// <param name="node">The node to convert to JSON.</param>
/// <returns>A JSON string of the <see cref="XNode"/>.</returns> /// <returns>A JSON string of the <see cref="XNode"/>.</returns>
public static string SerializeXNode(XObject? node) public static string SerializeXNode(XObject node)
{ {
return SerializeXNode(node, Formatting.None); return SerializeXNode(node, Formatting.None);
} }
@ -997,7 +996,7 @@ namespace LC.Newtonsoft.Json
/// <param name="node">The node to convert to JSON.</param> /// <param name="node">The node to convert to JSON.</param>
/// <param name="formatting">Indicates how the output should be formatted.</param> /// <param name="formatting">Indicates how the output should be formatted.</param>
/// <returns>A JSON string of the <see cref="XNode"/>.</returns> /// <returns>A JSON string of the <see cref="XNode"/>.</returns>
public static string SerializeXNode(XObject? node, Formatting formatting) public static string SerializeXNode(XObject node, Formatting formatting)
{ {
return SerializeXNode(node, formatting, false); return SerializeXNode(node, formatting, false);
} }
@ -1009,7 +1008,7 @@ namespace LC.Newtonsoft.Json
/// <param name="formatting">Indicates how the output should be formatted.</param> /// <param name="formatting">Indicates how the output should be formatted.</param>
/// <param name="omitRootObject">Omits writing the root object.</param> /// <param name="omitRootObject">Omits writing the root object.</param>
/// <returns>A JSON string of the <see cref="XNode"/>.</returns> /// <returns>A JSON string of the <see cref="XNode"/>.</returns>
public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject) public static string SerializeXNode(XObject node, Formatting formatting, bool omitRootObject)
{ {
XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject }; XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject };
@ -1021,7 +1020,7 @@ namespace LC.Newtonsoft.Json
/// </summary> /// </summary>
/// <param name="value">The JSON string.</param> /// <param name="value">The JSON string.</param>
/// <returns>The deserialized <see cref="XNode"/>.</returns> /// <returns>The deserialized <see cref="XNode"/>.</returns>
public static XDocument? DeserializeXNode(string value) public static XDocument DeserializeXNode(string value)
{ {
return DeserializeXNode(value, null); return DeserializeXNode(value, null);
} }
@ -1032,7 +1031,7 @@ namespace LC.Newtonsoft.Json
/// <param name="value">The JSON string.</param> /// <param name="value">The JSON string.</param>
/// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param> /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
/// <returns>The deserialized <see cref="XNode"/>.</returns> /// <returns>The deserialized <see cref="XNode"/>.</returns>
public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName) public static XDocument DeserializeXNode(string value, string deserializeRootElementName)
{ {
return DeserializeXNode(value, deserializeRootElementName, false); return DeserializeXNode(value, deserializeRootElementName, false);
} }
@ -1048,7 +1047,7 @@ namespace LC.Newtonsoft.Json
/// This attribute helps preserve arrays when converting the written XML back to JSON. /// This attribute helps preserve arrays when converting the written XML back to JSON.
/// </param> /// </param>
/// <returns>The deserialized <see cref="XNode"/>.</returns> /// <returns>The deserialized <see cref="XNode"/>.</returns>
public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) public static XDocument DeserializeXNode(string value, string deserializeRootElementName, bool writeArrayAttribute)
{ {
return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, false); return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, false);
} }
@ -1070,14 +1069,14 @@ namespace LC.Newtonsoft.Json
/// as part of the XML element name. /// as part of the XML element name.
/// </param> /// </param>
/// <returns>The deserialized <see cref="XNode"/>.</returns> /// <returns>The deserialized <see cref="XNode"/>.</returns>
public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) public static XDocument DeserializeXNode(string value, string deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters)
{ {
XmlNodeConverter converter = new XmlNodeConverter(); XmlNodeConverter converter = new XmlNodeConverter();
converter.DeserializeRootElementName = deserializeRootElementName; converter.DeserializeRootElementName = deserializeRootElementName;
converter.WriteArrayAttribute = writeArrayAttribute; converter.WriteArrayAttribute = writeArrayAttribute;
converter.EncodeSpecialCharacters = encodeSpecialCharacters; converter.EncodeSpecialCharacters = encodeSpecialCharacters;
return (XDocument?)DeserializeObject(value, typeof(XDocument), converter); return (XDocument)DeserializeObject(value, typeof(XDocument), converter);
} }
#endif #endif
#endregion #endregion

View File

@ -26,8 +26,6 @@
using System; using System;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using System.Globalization; using System.Globalization;
using System.Runtime.CompilerServices;
using System.Diagnostics.CodeAnalysis;
namespace LC.Newtonsoft.Json namespace LC.Newtonsoft.Json
{ {
@ -42,7 +40,7 @@ namespace LC.Newtonsoft.Json
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer); public abstract void WriteJson(JsonWriter writer, object value, JsonSerializer serializer);
/// <summary> /// <summary>
/// Reads the JSON representation of the object. /// Reads the JSON representation of the object.
@ -52,7 +50,7 @@ namespace LC.Newtonsoft.Json
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer); public abstract object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer);
/// <summary> /// <summary>
/// Determines whether this instance can convert the specified object type. /// Determines whether this instance can convert the specified object type.
@ -88,13 +86,13 @@ namespace LC.Newtonsoft.Json
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) public sealed override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (!(value != null ? value is T : ReflectionUtils.IsNullable(typeof(T)))) if (!(value != null ? value is T : ReflectionUtils.IsNullable(typeof(T))))
{ {
throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T)));
} }
WriteJson(writer, (T?)value, serializer); WriteJson(writer, (T)value, serializer);
} }
/// <summary> /// <summary>
@ -103,7 +101,7 @@ namespace LC.Newtonsoft.Json
/// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer); public abstract void WriteJson(JsonWriter writer, T value, JsonSerializer serializer);
/// <summary> /// <summary>
/// Reads the JSON representation of the object. /// Reads the JSON representation of the object.
@ -113,14 +111,14 @@ namespace LC.Newtonsoft.Json
/// <param name="existingValue">The existing value of object being read.</param> /// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) public sealed override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{ {
bool existingIsNull = existingValue == null; bool existingIsNull = existingValue == null;
if (!(existingIsNull || existingValue is T)) if (!(existingIsNull || existingValue is T))
{ {
throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T)));
} }
return ReadJson(reader, objectType, existingIsNull ? default : (T?)existingValue, !existingIsNull, serializer); return ReadJson(reader, objectType, existingIsNull ? default : (T)existingValue, !existingIsNull, serializer);
} }
/// <summary> /// <summary>
@ -132,7 +130,7 @@ namespace LC.Newtonsoft.Json
/// <param name="hasExistingValue">The existing value has a value.</param> /// <param name="hasExistingValue">The existing value has a value.</param>
/// <param name="serializer">The calling serializer.</param> /// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns> /// <returns>The object value.</returns>
public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer); public abstract T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer);
/// <summary> /// <summary>
/// Determines whether this instance can convert the specified object type. /// Determines whether this instance can convert the specified object type.

View File

@ -47,7 +47,7 @@ namespace LC.Newtonsoft.Json
/// The parameter list to use when constructing the <see cref="JsonConverter"/> described by <see cref="ConverterType"/>. /// The parameter list to use when constructing the <see cref="JsonConverter"/> described by <see cref="ConverterType"/>.
/// If <c>null</c>, the default constructor is used. /// If <c>null</c>, the default constructor is used.
/// </summary> /// </summary>
public object[]? ConverterParameters { get; } public object[] ConverterParameters { get; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="JsonConverterAttribute"/> class. /// Initializes a new instance of the <see cref="JsonConverterAttribute"/> class.

View File

@ -63,7 +63,7 @@ namespace LC.Newtonsoft.Json
/// </summary> /// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param> /// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or <c>null</c> if no inner exception is specified.</param> /// <param name="innerException">The exception that is the cause of the current exception, or <c>null</c> if no inner exception is specified.</param>
public JsonException(string message, Exception? innerException) public JsonException(string message, Exception innerException)
: base(message, innerException) : base(message, innerException)
{ {
} }

View File

@ -12,6 +12,6 @@
/// <param name="start">The zero-based index into the array specifying the first character of the name.</param> /// <param name="start">The zero-based index into the array specifying the first character of the name.</param>
/// <param name="length">The number of characters in the name.</param> /// <param name="length">The number of characters in the name.</param>
/// <returns>A string containing the same characters as the specified range of characters in the given array.</returns> /// <returns>A string containing the same characters as the specified range of characters in the given array.</returns>
public abstract string? Get(char[] key, int start, int length); public abstract string Get(char[] key, int start, int length);
} }
} }

View File

@ -46,7 +46,7 @@ namespace LC.Newtonsoft.Json
internal JsonContainerType Type; internal JsonContainerType Type;
internal int Position; internal int Position;
internal string? PropertyName; internal string PropertyName;
internal bool HasIndex; internal bool HasIndex;
public JsonPosition(JsonContainerType type) public JsonPosition(JsonContainerType type)
@ -62,7 +62,7 @@ namespace LC.Newtonsoft.Json
switch (Type) switch (Type)
{ {
case JsonContainerType.Object: case JsonContainerType.Object:
return PropertyName!.Length + 5; return PropertyName.Length + 5;
case JsonContainerType.Array: case JsonContainerType.Array:
case JsonContainerType.Constructor: case JsonContainerType.Constructor:
return MathUtils.IntLength((ulong)Position) + 2; return MathUtils.IntLength((ulong)Position) + 2;
@ -71,12 +71,12 @@ namespace LC.Newtonsoft.Json
} }
} }
internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer) internal void WriteTo(StringBuilder sb, ref StringWriter writer, ref char[] buffer)
{ {
switch (Type) switch (Type)
{ {
case JsonContainerType.Object: case JsonContainerType.Object:
string propertyName = PropertyName!; string propertyName = PropertyName;
if (propertyName.IndexOfAny(SpecialCharacters) != -1) if (propertyName.IndexOfAny(SpecialCharacters) != -1)
{ {
sb.Append(@"['"); sb.Append(@"['");
@ -130,8 +130,8 @@ namespace LC.Newtonsoft.Json
} }
StringBuilder sb = new StringBuilder(capacity); StringBuilder sb = new StringBuilder(capacity);
StringWriter? writer = null; StringWriter writer = null;
char[]? buffer = null; char[] buffer = null;
if (positions != null) if (positions != null)
{ {
foreach (JsonPosition state in positions) foreach (JsonPosition state in positions)
@ -147,7 +147,7 @@ namespace LC.Newtonsoft.Json
return sb.ToString(); return sb.ToString();
} }
internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message) internal static string FormatMessage(IJsonLineInfo lineInfo, string path, string message)
{ {
// don't add a fullstop and space when message ends with a new line // don't add a fullstop and space when message ends with a new line
if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal)) if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal))

View File

@ -52,7 +52,7 @@ namespace LC.Newtonsoft.Json
/// Gets or sets the <see cref="JsonConverter"/> type used when serializing the property's collection items. /// Gets or sets the <see cref="JsonConverter"/> type used when serializing the property's collection items.
/// </summary> /// </summary>
/// <value>The collection's items <see cref="JsonConverter"/> type.</value> /// <value>The collection's items <see cref="JsonConverter"/> type.</value>
public Type? ItemConverterType { get; set; } public Type ItemConverterType { get; set; }
/// <summary> /// <summary>
/// The parameter list to use when constructing the <see cref="JsonConverter"/> described by <see cref="ItemConverterType"/>. /// The parameter list to use when constructing the <see cref="JsonConverter"/> described by <see cref="ItemConverterType"/>.
@ -65,13 +65,13 @@ namespace LC.Newtonsoft.Json
/// [JsonProperty(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })] /// [JsonProperty(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })]
/// </code> /// </code>
/// </example> /// </example>
public object[]? ItemConverterParameters { get; set; } public object[] ItemConverterParameters { get; set; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="Type"/> of the <see cref="NamingStrategy"/>. /// Gets or sets the <see cref="Type"/> of the <see cref="NamingStrategy"/>.
/// </summary> /// </summary>
/// <value>The <see cref="Type"/> of the <see cref="NamingStrategy"/>.</value> /// <value>The <see cref="Type"/> of the <see cref="NamingStrategy"/>.</value>
public Type? NamingStrategyType { get; set; } public Type NamingStrategyType { get; set; }
/// <summary> /// <summary>
/// The parameter list to use when constructing the <see cref="NamingStrategy"/> described by <see cref="JsonPropertyAttribute.NamingStrategyType"/>. /// The parameter list to use when constructing the <see cref="NamingStrategy"/> described by <see cref="JsonPropertyAttribute.NamingStrategyType"/>.
@ -84,7 +84,7 @@ namespace LC.Newtonsoft.Json
/// [JsonProperty(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })] /// [JsonProperty(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })]
/// </code> /// </code>
/// </example> /// </example>
public object[]? NamingStrategyParameters { get; set; } public object[] NamingStrategyParameters { get; set; }
/// <summary> /// <summary>
/// Gets or sets the null value handling used when serializing this property. /// Gets or sets the null value handling used when serializing this property.
@ -172,7 +172,7 @@ namespace LC.Newtonsoft.Json
/// Gets or sets the name of the property. /// Gets or sets the name of the property.
/// </summary> /// </summary>
/// <value>The name of the property.</value> /// <value>The name of the property.</value>
public string? PropertyName { get; set; } public string PropertyName { get; set; }
/// <summary> /// <summary>
/// Gets or sets the reference loop handling used when serializing the property's collection items. /// Gets or sets the reference loop handling used when serializing the property's collection items.

View File

@ -101,12 +101,12 @@ namespace LC.Newtonsoft.Json
/// property returns the <see cref="byte"/>[]. This result will be <c>null</c> at the end of an array.</returns> /// property returns the <see cref="byte"/>[]. This result will be <c>null</c> at the end of an array.</returns>
/// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
/// classes can override this behaviour for true asynchronicity.</remarks> /// classes can override this behaviour for true asynchronicity.</remarks>
public virtual Task<byte[]?> ReadAsBytesAsync(CancellationToken cancellationToken = default) public virtual Task<byte[]> ReadAsBytesAsync(CancellationToken cancellationToken = default)
{ {
return cancellationToken.CancelIfRequestedAsync<byte[]?>() ?? Task.FromResult(ReadAsBytes()); return cancellationToken.CancelIfRequestedAsync<byte[]>() ?? Task.FromResult(ReadAsBytes());
} }
internal async Task<byte[]?> ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken) internal async Task<byte[]> ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken)
{ {
List<byte> buffer = new List<byte>(); List<byte> buffer = new List<byte>();
@ -199,9 +199,9 @@ namespace LC.Newtonsoft.Json
/// property returns the <see cref="string"/>. This result will be <c>null</c> at the end of an array.</returns> /// property returns the <see cref="string"/>. This result will be <c>null</c> at the end of an array.</returns>
/// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
/// classes can override this behaviour for true asynchronicity.</remarks> /// classes can override this behaviour for true asynchronicity.</remarks>
public virtual Task<string?> ReadAsStringAsync(CancellationToken cancellationToken = default) public virtual Task<string> ReadAsStringAsync(CancellationToken cancellationToken = default)
{ {
return cancellationToken.CancelIfRequestedAsync<string?>() ?? Task.FromResult(ReadAsString()); return cancellationToken.CancelIfRequestedAsync<string>() ?? Task.FromResult(ReadAsString());
} }
internal async Task<bool> ReadAndMoveToContentAsync(CancellationToken cancellationToken) internal async Task<bool> ReadAndMoveToContentAsync(CancellationToken cancellationToken)

View File

@ -113,18 +113,18 @@ namespace LC.Newtonsoft.Json
// current Token data // current Token data
private JsonToken _tokenType; private JsonToken _tokenType;
private object? _value; private object _value;
internal char _quoteChar; internal char _quoteChar;
internal State _currentState; internal State _currentState;
private JsonPosition _currentPosition; private JsonPosition _currentPosition;
private CultureInfo? _culture; private CultureInfo _culture;
private DateTimeZoneHandling _dateTimeZoneHandling; private DateTimeZoneHandling _dateTimeZoneHandling;
private int? _maxDepth; private int? _maxDepth;
private bool _hasExceededMaxDepth; private bool _hasExceededMaxDepth;
internal DateParseHandling _dateParseHandling; internal DateParseHandling _dateParseHandling;
internal FloatParseHandling _floatParseHandling; internal FloatParseHandling _floatParseHandling;
private string? _dateFormatString; private string _dateFormatString;
private List<JsonPosition>? _stack; private List<JsonPosition> _stack;
/// <summary> /// <summary>
/// Gets the current reader state. /// Gets the current reader state.
@ -219,7 +219,7 @@ namespace LC.Newtonsoft.Json
/// <summary> /// <summary>
/// Gets or sets how custom date formatted strings are parsed when reading JSON. /// Gets or sets how custom date formatted strings are parsed when reading JSON.
/// </summary> /// </summary>
public string? DateFormatString public string DateFormatString
{ {
get => _dateFormatString; get => _dateFormatString;
set => _dateFormatString = value; set => _dateFormatString = value;
@ -227,8 +227,6 @@ namespace LC.Newtonsoft.Json
/// <summary> /// <summary>
/// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>. /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>.
/// A null value means there is no maximum.
/// The default value is <c>128</c>.
/// </summary> /// </summary>
public int? MaxDepth public int? MaxDepth
{ {
@ -252,12 +250,12 @@ namespace LC.Newtonsoft.Json
/// <summary> /// <summary>
/// Gets the text value of the current JSON token. /// Gets the text value of the current JSON token.
/// </summary> /// </summary>
public virtual object? Value => _value; public virtual object Value => _value;
/// <summary> /// <summary>
/// Gets the .NET type for the current JSON token. /// Gets the .NET type for the current JSON token.
/// </summary> /// </summary>
public virtual Type? ValueType => _value?.GetType(); public virtual Type ValueType => _value?.GetType();
/// <summary> /// <summary>
/// Gets the depth of the current token in the JSON document. /// Gets the depth of the current token in the JSON document.
@ -297,7 +295,7 @@ namespace LC.Newtonsoft.Json
JsonPosition? current = insideContainer ? (JsonPosition?)_currentPosition : null; JsonPosition? current = insideContainer ? (JsonPosition?)_currentPosition : null;
return JsonPosition.BuildPath(_stack!, current); return JsonPosition.BuildPath(_stack, current);
} }
} }
@ -329,7 +327,6 @@ namespace LC.Newtonsoft.Json
_dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
_dateParseHandling = DateParseHandling.DateTime; _dateParseHandling = DateParseHandling.DateTime;
_floatParseHandling = FloatParseHandling.Double; _floatParseHandling = FloatParseHandling.Double;
_maxDepth = 64;
CloseInput = true; CloseInput = true;
} }
@ -411,7 +408,7 @@ namespace LC.Newtonsoft.Json
return null; return null;
case JsonToken.Integer: case JsonToken.Integer:
case JsonToken.Float: case JsonToken.Float:
object v = Value!; object v = Value;
if (v is int i) if (v is int i)
{ {
return i; return i;
@ -439,16 +436,16 @@ namespace LC.Newtonsoft.Json
SetToken(JsonToken.Integer, i, false); SetToken(JsonToken.Integer, i, false);
return i; return i;
case JsonToken.String: case JsonToken.String:
string? s = (string?)Value; string s = (string)Value;
return ReadInt32String(s); return ReadInt32String(s);
} }
throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
} }
internal int? ReadInt32String(string? s) internal int? ReadInt32String(string s)
{ {
if (StringUtils.IsNullOrEmpty(s)) if (string.IsNullOrEmpty(s))
{ {
SetToken(JsonToken.Null, null, false); SetToken(JsonToken.Null, null, false);
return null; return null;
@ -470,7 +467,7 @@ namespace LC.Newtonsoft.Json
/// Reads the next JSON token from the source as a <see cref="String"/>. /// Reads the next JSON token from the source as a <see cref="String"/>.
/// </summary> /// </summary>
/// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns> /// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
public virtual string? ReadAsString() public virtual string ReadAsString()
{ {
JsonToken t = GetContentToken(); JsonToken t = GetContentToken();
@ -481,12 +478,12 @@ namespace LC.Newtonsoft.Json
case JsonToken.EndArray: case JsonToken.EndArray:
return null; return null;
case JsonToken.String: case JsonToken.String:
return (string?)Value; return (string)Value;
} }
if (JsonTokenUtils.IsPrimitiveToken(t)) if (JsonTokenUtils.IsPrimitiveToken(t))
{ {
object? v = Value; object v = Value;
if (v != null) if (v != null)
{ {
string s; string s;
@ -511,7 +508,7 @@ namespace LC.Newtonsoft.Json
/// Reads the next JSON token from the source as a <see cref="Byte"/>[]. /// Reads the next JSON token from the source as a <see cref="Byte"/>[].
/// </summary> /// </summary>
/// <returns>A <see cref="Byte"/>[] or <c>null</c> if the next JSON token is null. This method will return <c>null</c> at the end of an array.</returns> /// <returns>A <see cref="Byte"/>[] or <c>null</c> if the next JSON token is null. This method will return <c>null</c> at the end of an array.</returns>
public virtual byte[]? ReadAsBytes() public virtual byte[] ReadAsBytes()
{ {
JsonToken t = GetContentToken(); JsonToken t = GetContentToken();
@ -521,7 +518,7 @@ namespace LC.Newtonsoft.Json
{ {
ReadIntoWrappedTypeObject(); ReadIntoWrappedTypeObject();
byte[]? data = ReadAsBytes(); byte[] data = ReadAsBytes();
ReaderReadAndAssert(); ReaderReadAndAssert();
if (TokenType != JsonToken.EndObject) if (TokenType != JsonToken.EndObject)
@ -536,7 +533,7 @@ namespace LC.Newtonsoft.Json
{ {
// attempt to convert possible base 64 or GUID string to bytes // attempt to convert possible base 64 or GUID string to bytes
// GUID has to have format 00000000-0000-0000-0000-000000000000 // GUID has to have format 00000000-0000-0000-0000-000000000000
string s = (string)Value!; string s = (string)Value;
byte[] data; byte[] data;
@ -568,7 +565,7 @@ namespace LC.Newtonsoft.Json
return data; return data;
} }
return (byte[]?)Value; return (byte[])Value;
case JsonToken.StartArray: case JsonToken.StartArray:
return ReadArrayIntoByteArray(); return ReadArrayIntoByteArray();
} }
@ -630,7 +627,7 @@ namespace LC.Newtonsoft.Json
return null; return null;
case JsonToken.Integer: case JsonToken.Integer:
case JsonToken.Float: case JsonToken.Float:
object v = Value!; object v = Value;
if (v is double d) if (v is double d)
{ {
return d; return d;
@ -651,15 +648,15 @@ namespace LC.Newtonsoft.Json
return (double)d; return (double)d;
case JsonToken.String: case JsonToken.String:
return ReadDoubleString((string?)Value); return ReadDoubleString((string)Value);
} }
throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
} }
internal double? ReadDoubleString(string? s) internal double? ReadDoubleString(string s)
{ {
if (StringUtils.IsNullOrEmpty(s)) if (string.IsNullOrEmpty(s))
{ {
SetToken(JsonToken.Null, null, false); SetToken(JsonToken.Null, null, false);
return null; return null;
@ -708,17 +705,17 @@ namespace LC.Newtonsoft.Json
SetToken(JsonToken.Boolean, b, false); SetToken(JsonToken.Boolean, b, false);
return b; return b;
case JsonToken.String: case JsonToken.String:
return ReadBooleanString((string?)Value); return ReadBooleanString((string)Value);
case JsonToken.Boolean: case JsonToken.Boolean:
return (bool)Value!; return (bool)Value;
} }
throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
} }
internal bool? ReadBooleanString(string? s) internal bool? ReadBooleanString(string s)
{ {
if (StringUtils.IsNullOrEmpty(s)) if (string.IsNullOrEmpty(s))
{ {
SetToken(JsonToken.Null, null, false); SetToken(JsonToken.Null, null, false);
return null; return null;
@ -752,7 +749,7 @@ namespace LC.Newtonsoft.Json
return null; return null;
case JsonToken.Integer: case JsonToken.Integer:
case JsonToken.Float: case JsonToken.Float:
object v = Value!; object v = Value;
if (v is decimal d) if (v is decimal d)
{ {
@ -781,15 +778,15 @@ namespace LC.Newtonsoft.Json
SetToken(JsonToken.Float, d, false); SetToken(JsonToken.Float, d, false);
return d; return d;
case JsonToken.String: case JsonToken.String:
return ReadDecimalString((string?)Value); return ReadDecimalString((string)Value);
} }
throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
} }
internal decimal? ReadDecimalString(string? s) internal decimal? ReadDecimalString(string s)
{ {
if (StringUtils.IsNullOrEmpty(s)) if (string.IsNullOrEmpty(s))
{ {
SetToken(JsonToken.Null, null, false); SetToken(JsonToken.Null, null, false);
return null; return null;
@ -833,17 +830,18 @@ namespace LC.Newtonsoft.Json
} }
#endif #endif
return (DateTime)Value!; return (DateTime)Value;
case JsonToken.String: case JsonToken.String:
return ReadDateTimeString((string?)Value); string s = (string)Value;
return ReadDateTimeString(s);
} }
throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
} }
internal DateTime? ReadDateTimeString(string? s) internal DateTime? ReadDateTimeString(string s)
{ {
if (StringUtils.IsNullOrEmpty(s)) if (string.IsNullOrEmpty(s))
{ {
SetToken(JsonToken.Null, null, false); SetToken(JsonToken.Null, null, false);
return null; return null;
@ -887,18 +885,18 @@ namespace LC.Newtonsoft.Json
SetToken(JsonToken.Date, new DateTimeOffset(time), false); SetToken(JsonToken.Date, new DateTimeOffset(time), false);
} }
return (DateTimeOffset)Value!; return (DateTimeOffset)Value;
case JsonToken.String: case JsonToken.String:
string? s = (string?)Value; string s = (string)Value;
return ReadDateTimeOffsetString(s); return ReadDateTimeOffsetString(s);
default: default:
throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t)); throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
} }
} }
internal DateTimeOffset? ReadDateTimeOffsetString(string? s) internal DateTimeOffset? ReadDateTimeOffsetString(string s)
{ {
if (StringUtils.IsNullOrEmpty(s)) if (string.IsNullOrEmpty(s))
{ {
SetToken(JsonToken.Null, null, false); SetToken(JsonToken.Null, null, false);
return null; return null;
@ -987,7 +985,7 @@ namespace LC.Newtonsoft.Json
/// </summary> /// </summary>
/// <param name="newToken">The new token.</param> /// <param name="newToken">The new token.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
protected void SetToken(JsonToken newToken, object? value) protected void SetToken(JsonToken newToken, object value)
{ {
SetToken(newToken, value, true); SetToken(newToken, value, true);
} }
@ -998,7 +996,7 @@ namespace LC.Newtonsoft.Json
/// <param name="newToken">The new token.</param> /// <param name="newToken">The new token.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="updateIndex">A flag indicating whether the position index inside an array should be updated.</param> /// <param name="updateIndex">A flag indicating whether the position index inside an array should be updated.</param>
protected void SetToken(JsonToken newToken, object? value, bool updateIndex) protected void SetToken(JsonToken newToken, object value, bool updateIndex)
{ {
_tokenType = newToken; _tokenType = newToken;
_value = value; _value = value;
@ -1029,7 +1027,7 @@ namespace LC.Newtonsoft.Json
case JsonToken.PropertyName: case JsonToken.PropertyName:
_currentState = State.Property; _currentState = State.Property;
_currentPosition.PropertyName = (string)value!; _currentPosition.PropertyName = (string)value;
break; break;
case JsonToken.Undefined: case JsonToken.Undefined:
case JsonToken.Integer: case JsonToken.Integer:
@ -1172,7 +1170,7 @@ namespace LC.Newtonsoft.Json
} }
} }
internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter) internal void ReadForTypeAndAssert(JsonContract contract, bool hasConverter)
{ {
if (!ReadForType(contract, hasConverter)) if (!ReadForType(contract, hasConverter))
{ {
@ -1180,7 +1178,7 @@ namespace LC.Newtonsoft.Json
} }
} }
internal bool ReadForType(JsonContract? contract, bool hasConverter) internal bool ReadForType(JsonContract contract, bool hasConverter)
{ {
// don't read properties with converters as a specific value // don't read properties with converters as a specific value
// the value might be a string which will then get converted which will error if read as date for example // the value might be a string which will then get converted which will error if read as date for example

View File

@ -54,7 +54,7 @@ namespace LC.Newtonsoft.Json
/// Gets the path to the JSON where the error occurred. /// Gets the path to the JSON where the error occurred.
/// </summary> /// </summary>
/// <value>The path to the JSON where the error occurred.</value> /// <value>The path to the JSON where the error occurred.</value>
public string? Path { get; } public string Path { get; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="JsonReaderException"/> class. /// Initializes a new instance of the <see cref="JsonReaderException"/> class.
@ -107,7 +107,7 @@ namespace LC.Newtonsoft.Json
/// <param name="lineNumber">The line number indicating where the error occurred.</param> /// <param name="lineNumber">The line number indicating where the error occurred.</param>
/// <param name="linePosition">The line position indicating where the error occurred.</param> /// <param name="linePosition">The line position indicating where the error occurred.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or <c>null</c> if no inner exception is specified.</param> /// <param name="innerException">The exception that is the cause of the current exception, or <c>null</c> if no inner exception is specified.</param>
public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException) public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception innerException)
: base(message, innerException) : base(message, innerException)
{ {
Path = path; Path = path;
@ -120,12 +120,12 @@ namespace LC.Newtonsoft.Json
return Create(reader, message, null); return Create(reader, message, null);
} }
internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex) internal static JsonReaderException Create(JsonReader reader, string message, Exception ex)
{ {
return Create(reader as IJsonLineInfo, reader.Path, message, ex); return Create(reader as IJsonLineInfo, reader.Path, message, ex);
} }
internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) internal static JsonReaderException Create(IJsonLineInfo lineInfo, string path, string message, Exception ex)
{ {
message = JsonPosition.FormatMessage(lineInfo, path, message); message = JsonPosition.FormatMessage(lineInfo, path, message);

View File

@ -54,7 +54,7 @@ namespace LC.Newtonsoft.Json
/// Gets the path to the JSON where the error occurred. /// Gets the path to the JSON where the error occurred.
/// </summary> /// </summary>
/// <value>The path to the JSON where the error occurred.</value> /// <value>The path to the JSON where the error occurred.</value>
public string? Path { get; } public string Path { get; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="JsonSerializationException"/> class. /// Initializes a new instance of the <see cref="JsonSerializationException"/> class.
@ -107,7 +107,7 @@ namespace LC.Newtonsoft.Json
/// <param name="lineNumber">The line number indicating where the error occurred.</param> /// <param name="lineNumber">The line number indicating where the error occurred.</param>
/// <param name="linePosition">The line position indicating where the error occurred.</param> /// <param name="linePosition">The line position indicating where the error occurred.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or <c>null</c> if no inner exception is specified.</param> /// <param name="innerException">The exception that is the cause of the current exception, or <c>null</c> if no inner exception is specified.</param>
public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException) public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception innerException)
: base(message, innerException) : base(message, innerException)
{ {
Path = path; Path = path;
@ -120,12 +120,12 @@ namespace LC.Newtonsoft.Json
return Create(reader, message, null); return Create(reader, message, null);
} }
internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex) internal static JsonSerializationException Create(JsonReader reader, string message, Exception ex)
{ {
return Create(reader as IJsonLineInfo, reader.Path, message, ex); return Create(reader as IJsonLineInfo, reader.Path, message, ex);
} }
internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) internal static JsonSerializationException Create(IJsonLineInfo lineInfo, string path, string message, Exception ex)
{ {
message = JsonPosition.FormatMessage(lineInfo, path, message); message = JsonPosition.FormatMessage(lineInfo, path, message);

View File

@ -35,8 +35,6 @@ using LC.Newtonsoft.Json.Serialization;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using ErrorEventArgs = LC.Newtonsoft.Json.Serialization.ErrorEventArgs; using ErrorEventArgs = LC.Newtonsoft.Json.Serialization.ErrorEventArgs;
using System.Runtime.CompilerServices;
using System.Diagnostics.CodeAnalysis;
namespace LC.Newtonsoft.Json namespace LC.Newtonsoft.Json
{ {
@ -56,13 +54,13 @@ namespace LC.Newtonsoft.Json
internal DefaultValueHandling _defaultValueHandling; internal DefaultValueHandling _defaultValueHandling;
internal ConstructorHandling _constructorHandling; internal ConstructorHandling _constructorHandling;
internal MetadataPropertyHandling _metadataPropertyHandling; internal MetadataPropertyHandling _metadataPropertyHandling;
internal JsonConverterCollection? _converters; internal JsonConverterCollection _converters;
internal IContractResolver _contractResolver; internal IContractResolver _contractResolver;
internal ITraceWriter? _traceWriter; internal ITraceWriter _traceWriter;
internal IEqualityComparer? _equalityComparer; internal IEqualityComparer _equalityComparer;
internal ISerializationBinder _serializationBinder; internal ISerializationBinder _serializationBinder;
internal StreamingContext _context; internal StreamingContext _context;
private IReferenceResolver? _referenceResolver; private IReferenceResolver _referenceResolver;
private Formatting? _formatting; private Formatting? _formatting;
private DateFormatHandling? _dateFormatHandling; private DateFormatHandling? _dateFormatHandling;
@ -75,18 +73,18 @@ namespace LC.Newtonsoft.Json
private int? _maxDepth; private int? _maxDepth;
private bool _maxDepthSet; private bool _maxDepthSet;
private bool? _checkAdditionalContent; private bool? _checkAdditionalContent;
private string? _dateFormatString; private string _dateFormatString;
private bool _dateFormatStringSet; private bool _dateFormatStringSet;
/// <summary> /// <summary>
/// Occurs when the <see cref="JsonSerializer"/> errors during serialization and deserialization. /// Occurs when the <see cref="JsonSerializer"/> errors during serialization and deserialization.
/// </summary> /// </summary>
public virtual event EventHandler<ErrorEventArgs>? Error; public virtual event EventHandler<ErrorEventArgs> Error;
/// <summary> /// <summary>
/// Gets or sets the <see cref="IReferenceResolver"/> used by the serializer when resolving references. /// Gets or sets the <see cref="IReferenceResolver"/> used by the serializer when resolving references.
/// </summary> /// </summary>
public virtual IReferenceResolver? ReferenceResolver public virtual IReferenceResolver ReferenceResolver
{ {
get => GetReferenceResolver(); get => GetReferenceResolver();
set set
@ -108,6 +106,11 @@ namespace LC.Newtonsoft.Json
{ {
get get
{ {
if (_serializationBinder == null)
{
return null;
}
if (_serializationBinder is SerializationBinder legacySerializationBinder) if (_serializationBinder is SerializationBinder legacySerializationBinder)
{ {
return legacySerializationBinder; return legacySerializationBinder;
@ -152,7 +155,7 @@ namespace LC.Newtonsoft.Json
/// Gets or sets the <see cref="ITraceWriter"/> used by the serializer when writing trace messages. /// Gets or sets the <see cref="ITraceWriter"/> used by the serializer when writing trace messages.
/// </summary> /// </summary>
/// <value>The trace writer.</value> /// <value>The trace writer.</value>
public virtual ITraceWriter? TraceWriter public virtual ITraceWriter TraceWriter
{ {
get => _traceWriter; get => _traceWriter;
set => _traceWriter = value; set => _traceWriter = value;
@ -162,7 +165,7 @@ namespace LC.Newtonsoft.Json
/// Gets or sets the equality comparer used by the serializer when comparing references. /// Gets or sets the equality comparer used by the serializer when comparing references.
/// </summary> /// </summary>
/// <value>The equality comparer.</value> /// <value>The equality comparer.</value>
public virtual IEqualityComparer? EqualityComparer public virtual IEqualityComparer EqualityComparer
{ {
get => _equalityComparer; get => _equalityComparer;
set => _equalityComparer = value; set => _equalityComparer = value;
@ -514,7 +517,7 @@ namespace LC.Newtonsoft.Json
/// <summary> /// <summary>
/// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>. /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>.
/// A null value means there is no maximum. /// A null value means there is no maximum.
/// The default value is <c>128</c>. /// The default value is <c>null</c>.
/// </summary> /// </summary>
public virtual int? MaxDepth public virtual int? MaxDepth
{ {
@ -596,7 +599,7 @@ namespace LC.Newtonsoft.Json
/// The <see cref="JsonSerializer"/> will not use default settings /// The <see cref="JsonSerializer"/> will not use default settings
/// from <see cref="JsonConvert.DefaultSettings"/>. /// from <see cref="JsonConvert.DefaultSettings"/>.
/// </returns> /// </returns>
public static JsonSerializer Create(JsonSerializerSettings? settings) public static JsonSerializer Create(JsonSerializerSettings settings)
{ {
JsonSerializer serializer = Create(); JsonSerializer serializer = Create();
@ -621,7 +624,7 @@ namespace LC.Newtonsoft.Json
public static JsonSerializer CreateDefault() public static JsonSerializer CreateDefault()
{ {
// copy static to local variable to avoid concurrency issues // copy static to local variable to avoid concurrency issues
JsonSerializerSettings? defaultSettings = JsonConvert.DefaultSettings?.Invoke(); JsonSerializerSettings defaultSettings = JsonConvert.DefaultSettings?.Invoke();
return Create(defaultSettings); return Create(defaultSettings);
} }
@ -637,7 +640,7 @@ namespace LC.Newtonsoft.Json
/// The <see cref="JsonSerializer"/> will use default settings /// The <see cref="JsonSerializer"/> will use default settings
/// from <see cref="JsonConvert.DefaultSettings"/> as well as the specified <see cref="JsonSerializerSettings"/>. /// from <see cref="JsonConvert.DefaultSettings"/> as well as the specified <see cref="JsonSerializerSettings"/>.
/// </returns> /// </returns>
public static JsonSerializer CreateDefault(JsonSerializerSettings? settings) public static JsonSerializer CreateDefault(JsonSerializerSettings settings)
{ {
JsonSerializer serializer = CreateDefault(); JsonSerializer serializer = CreateDefault();
if (settings != null) if (settings != null)
@ -811,14 +814,14 @@ namespace LC.Newtonsoft.Json
SetupReader( SetupReader(
reader, reader,
out CultureInfo? previousCulture, out CultureInfo previousCulture,
out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateTimeZoneHandling? previousDateTimeZoneHandling,
out DateParseHandling? previousDateParseHandling, out DateParseHandling? previousDateParseHandling,
out FloatParseHandling? previousFloatParseHandling, out FloatParseHandling? previousFloatParseHandling,
out int? previousMaxDepth, out int? previousMaxDepth,
out string? previousDateFormatString); out string previousDateFormatString);
TraceJsonReader? traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) TraceJsonReader traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
? CreateTraceJsonReader(reader) ? CreateTraceJsonReader(reader)
: null; : null;
@ -827,7 +830,7 @@ namespace LC.Newtonsoft.Json
if (traceJsonReader != null) if (traceJsonReader != null)
{ {
TraceWriter!.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null);
} }
ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString);
@ -839,20 +842,20 @@ namespace LC.Newtonsoft.Json
/// <param name="reader">The <see cref="JsonReader"/> that contains the JSON structure to deserialize.</param> /// <param name="reader">The <see cref="JsonReader"/> that contains the JSON structure to deserialize.</param>
/// <returns>The <see cref="Object"/> being deserialized.</returns> /// <returns>The <see cref="Object"/> being deserialized.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public object? Deserialize(JsonReader reader) public object Deserialize(JsonReader reader)
{ {
return Deserialize(reader, null); return Deserialize(reader, null);
} }
/// <summary> /// <summary>
/// Deserializes the JSON structure contained by the specified <see cref="TextReader"/> /// Deserializes the JSON structure contained by the specified <see cref="StringReader"/>
/// into an instance of the specified type. /// into an instance of the specified type.
/// </summary> /// </summary>
/// <param name="reader">The <see cref="TextReader"/> containing the object.</param> /// <param name="reader">The <see cref="TextReader"/> containing the object.</param>
/// <param name="objectType">The <see cref="Type"/> of object being deserialized.</param> /// <param name="objectType">The <see cref="Type"/> of object being deserialized.</param>
/// <returns>The instance of <paramref name="objectType"/> being deserialized.</returns> /// <returns>The instance of <paramref name="objectType"/> being deserialized.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public object? Deserialize(TextReader reader, Type objectType) public object Deserialize(TextReader reader, Type objectType)
{ {
return Deserialize(new JsonTextReader(reader), objectType); return Deserialize(new JsonTextReader(reader), objectType);
} }
@ -865,9 +868,9 @@ namespace LC.Newtonsoft.Json
/// <typeparam name="T">The type of the object to deserialize.</typeparam> /// <typeparam name="T">The type of the object to deserialize.</typeparam>
/// <returns>The instance of <typeparamref name="T"/> being deserialized.</returns> /// <returns>The instance of <typeparamref name="T"/> being deserialized.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public T? Deserialize<T>(JsonReader reader) public T Deserialize<T>(JsonReader reader)
{ {
return (T?)Deserialize(reader, typeof(T)); return (T)Deserialize(reader, typeof(T));
} }
/// <summary> /// <summary>
@ -878,34 +881,34 @@ namespace LC.Newtonsoft.Json
/// <param name="objectType">The <see cref="Type"/> of object being deserialized.</param> /// <param name="objectType">The <see cref="Type"/> of object being deserialized.</param>
/// <returns>The instance of <paramref name="objectType"/> being deserialized.</returns> /// <returns>The instance of <paramref name="objectType"/> being deserialized.</returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public object? Deserialize(JsonReader reader, Type? objectType) public object Deserialize(JsonReader reader, Type objectType)
{ {
return DeserializeInternal(reader, objectType); return DeserializeInternal(reader, objectType);
} }
internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType) internal virtual object DeserializeInternal(JsonReader reader, Type objectType)
{ {
ValidationUtils.ArgumentNotNull(reader, nameof(reader)); ValidationUtils.ArgumentNotNull(reader, nameof(reader));
SetupReader( SetupReader(
reader, reader,
out CultureInfo? previousCulture, out CultureInfo previousCulture,
out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateTimeZoneHandling? previousDateTimeZoneHandling,
out DateParseHandling? previousDateParseHandling, out DateParseHandling? previousDateParseHandling,
out FloatParseHandling? previousFloatParseHandling, out FloatParseHandling? previousFloatParseHandling,
out int? previousMaxDepth, out int? previousMaxDepth,
out string? previousDateFormatString); out string previousDateFormatString);
TraceJsonReader? traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) TraceJsonReader traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
? CreateTraceJsonReader(reader) ? CreateTraceJsonReader(reader)
: null; : null;
JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this); JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this);
object? value = serializerReader.Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); object value = serializerReader.Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent);
if (traceJsonReader != null) if (traceJsonReader != null)
{ {
TraceWriter!.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null);
} }
ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString);
@ -913,7 +916,7 @@ namespace LC.Newtonsoft.Json
return value; return value;
} }
private void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString) private void SetupReader(JsonReader reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString)
{ {
if (_culture != null && !_culture.Equals(reader.Culture)) if (_culture != null && !_culture.Equals(reader.Culture))
{ {
@ -984,7 +987,7 @@ namespace LC.Newtonsoft.Json
} }
} }
private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string? previousDateFormatString) private void ResetReader(JsonReader reader, CultureInfo previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string previousDateFormatString)
{ {
// reset reader back to previous options // reset reader back to previous options
if (previousCulture != null) if (previousCulture != null)
@ -1025,7 +1028,7 @@ namespace LC.Newtonsoft.Json
/// </summary> /// </summary>
/// <param name="textWriter">The <see cref="TextWriter"/> used to write the JSON structure.</param> /// <param name="textWriter">The <see cref="TextWriter"/> used to write the JSON structure.</param>
/// <param name="value">The <see cref="Object"/> to serialize.</param> /// <param name="value">The <see cref="Object"/> to serialize.</param>
public void Serialize(TextWriter textWriter, object? value) public void Serialize(TextWriter textWriter, object value)
{ {
Serialize(new JsonTextWriter(textWriter), value); Serialize(new JsonTextWriter(textWriter), value);
} }
@ -1041,7 +1044,7 @@ namespace LC.Newtonsoft.Json
/// This parameter is used when <see cref="JsonSerializer.TypeNameHandling"/> is <see cref="Json.TypeNameHandling.Auto"/> to write out the type name if the type of the value does not match. /// This parameter is used when <see cref="JsonSerializer.TypeNameHandling"/> is <see cref="Json.TypeNameHandling.Auto"/> to write out the type name if the type of the value does not match.
/// Specifying the type is optional. /// Specifying the type is optional.
/// </param> /// </param>
public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) public void Serialize(JsonWriter jsonWriter, object value, Type objectType)
{ {
SerializeInternal(jsonWriter, value, objectType); SerializeInternal(jsonWriter, value, objectType);
} }
@ -1057,7 +1060,7 @@ namespace LC.Newtonsoft.Json
/// This parameter is used when <see cref="TypeNameHandling"/> is Auto to write out the type name if the type of the value does not match. /// This parameter is used when <see cref="TypeNameHandling"/> is Auto to write out the type name if the type of the value does not match.
/// Specifying the type is optional. /// Specifying the type is optional.
/// </param> /// </param>
public void Serialize(TextWriter textWriter, object? value, Type objectType) public void Serialize(TextWriter textWriter, object value, Type objectType)
{ {
Serialize(new JsonTextWriter(textWriter), value, objectType); Serialize(new JsonTextWriter(textWriter), value, objectType);
} }
@ -1068,7 +1071,7 @@ namespace LC.Newtonsoft.Json
/// </summary> /// </summary>
/// <param name="jsonWriter">The <see cref="JsonWriter"/> used to write the JSON structure.</param> /// <param name="jsonWriter">The <see cref="JsonWriter"/> used to write the JSON structure.</param>
/// <param name="value">The <see cref="Object"/> to serialize.</param> /// <param name="value">The <see cref="Object"/> to serialize.</param>
public void Serialize(JsonWriter jsonWriter, object? value) public void Serialize(JsonWriter jsonWriter, object value)
{ {
SerializeInternal(jsonWriter, value, null); SerializeInternal(jsonWriter, value, null);
} }
@ -1084,7 +1087,7 @@ namespace LC.Newtonsoft.Json
return traceReader; return traceReader;
} }
internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType) internal virtual void SerializeInternal(JsonWriter jsonWriter, object value, Type objectType)
{ {
ValidationUtils.ArgumentNotNull(jsonWriter, nameof(jsonWriter)); ValidationUtils.ArgumentNotNull(jsonWriter, nameof(jsonWriter));
@ -1124,21 +1127,21 @@ namespace LC.Newtonsoft.Json
jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault(); jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault();
} }
CultureInfo? previousCulture = null; CultureInfo previousCulture = null;
if (_culture != null && !_culture.Equals(jsonWriter.Culture)) if (_culture != null && !_culture.Equals(jsonWriter.Culture))
{ {
previousCulture = jsonWriter.Culture; previousCulture = jsonWriter.Culture;
jsonWriter.Culture = _culture; jsonWriter.Culture = _culture;
} }
string? previousDateFormatString = null; string previousDateFormatString = null;
if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString) if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString)
{ {
previousDateFormatString = jsonWriter.DateFormatString; previousDateFormatString = jsonWriter.DateFormatString;
jsonWriter.DateFormatString = _dateFormatString; jsonWriter.DateFormatString = _dateFormatString;
} }
TraceJsonWriter? traceJsonWriter = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) TraceJsonWriter traceJsonWriter = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
? new TraceJsonWriter(jsonWriter) ? new TraceJsonWriter(jsonWriter)
: null; : null;
@ -1147,7 +1150,7 @@ namespace LC.Newtonsoft.Json
if (traceJsonWriter != null) if (traceJsonWriter != null)
{ {
TraceWriter!.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null); TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null);
} }
// reset writer back to previous options // reset writer back to previous options
@ -1191,12 +1194,12 @@ namespace LC.Newtonsoft.Json
return _referenceResolver; return _referenceResolver;
} }
internal JsonConverter? GetMatchingConverter(Type type) internal JsonConverter GetMatchingConverter(Type type)
{ {
return GetMatchingConverter(_converters, type); return GetMatchingConverter(_converters, type);
} }
internal static JsonConverter? GetMatchingConverter(IList<JsonConverter>? converters, Type objectType) internal static JsonConverter GetMatchingConverter(IList<JsonConverter> converters, Type objectType)
{ {
#if DEBUG #if DEBUG
ValidationUtils.ArgumentNotNull(objectType, nameof(objectType)); ValidationUtils.ArgumentNotNull(objectType, nameof(objectType));

View File

@ -61,7 +61,6 @@ namespace LC.Newtonsoft.Json
internal static readonly CultureInfo DefaultCulture; internal static readonly CultureInfo DefaultCulture;
internal const bool DefaultCheckAdditionalContent = false; internal const bool DefaultCheckAdditionalContent = false;
internal const string DefaultDateFormatString = @"yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; internal const string DefaultDateFormatString = @"yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
internal const int DefaultMaxDepth = 64;
internal Formatting? _formatting; internal Formatting? _formatting;
internal DateFormatHandling? _dateFormatHandling; internal DateFormatHandling? _dateFormatHandling;
@ -70,11 +69,11 @@ namespace LC.Newtonsoft.Json
internal FloatFormatHandling? _floatFormatHandling; internal FloatFormatHandling? _floatFormatHandling;
internal FloatParseHandling? _floatParseHandling; internal FloatParseHandling? _floatParseHandling;
internal StringEscapeHandling? _stringEscapeHandling; internal StringEscapeHandling? _stringEscapeHandling;
internal CultureInfo? _culture; internal CultureInfo _culture;
internal bool? _checkAdditionalContent; internal bool? _checkAdditionalContent;
internal int? _maxDepth; internal int? _maxDepth;
internal bool _maxDepthSet; internal bool _maxDepthSet;
internal string? _dateFormatString; internal string _dateFormatString;
internal bool _dateFormatStringSet; internal bool _dateFormatStringSet;
internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling; internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling;
internal DefaultValueHandling? _defaultValueHandling; internal DefaultValueHandling? _defaultValueHandling;
@ -226,27 +225,27 @@ namespace LC.Newtonsoft.Json
/// serializing .NET objects to JSON and vice versa. /// serializing .NET objects to JSON and vice versa.
/// </summary> /// </summary>
/// <value>The contract resolver.</value> /// <value>The contract resolver.</value>
public IContractResolver? ContractResolver { get; set; } public IContractResolver ContractResolver { get; set; }
/// <summary> /// <summary>
/// Gets or sets the equality comparer used by the serializer when comparing references. /// Gets or sets the equality comparer used by the serializer when comparing references.
/// </summary> /// </summary>
/// <value>The equality comparer.</value> /// <value>The equality comparer.</value>
public IEqualityComparer? EqualityComparer { get; set; } public IEqualityComparer EqualityComparer { get; set; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="IReferenceResolver"/> used by the serializer when resolving references. /// Gets or sets the <see cref="IReferenceResolver"/> used by the serializer when resolving references.
/// </summary> /// </summary>
/// <value>The reference resolver.</value> /// <value>The reference resolver.</value>
[Obsolete("ReferenceResolver property is obsolete. Use the ReferenceResolverProvider property to set the IReferenceResolver: settings.ReferenceResolverProvider = () => resolver")] [Obsolete("ReferenceResolver property is obsolete. Use the ReferenceResolverProvider property to set the IReferenceResolver: settings.ReferenceResolverProvider = () => resolver")]
public IReferenceResolver? ReferenceResolver public IReferenceResolver ReferenceResolver
{ {
get => ReferenceResolverProvider?.Invoke(); get => ReferenceResolverProvider?.Invoke();
set set
{ {
ReferenceResolverProvider = (value != null) ReferenceResolverProvider = (value != null)
? () => value ? () => value
: (Func<IReferenceResolver?>?)null; : (Func<IReferenceResolver>)null;
} }
} }
@ -254,20 +253,20 @@ namespace LC.Newtonsoft.Json
/// Gets or sets a function that creates the <see cref="IReferenceResolver"/> used by the serializer when resolving references. /// Gets or sets a function that creates the <see cref="IReferenceResolver"/> used by the serializer when resolving references.
/// </summary> /// </summary>
/// <value>A function that creates the <see cref="IReferenceResolver"/> used by the serializer when resolving references.</value> /// <value>A function that creates the <see cref="IReferenceResolver"/> used by the serializer when resolving references.</value>
public Func<IReferenceResolver?>? ReferenceResolverProvider { get; set; } public Func<IReferenceResolver> ReferenceResolverProvider { get; set; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="ITraceWriter"/> used by the serializer when writing trace messages. /// Gets or sets the <see cref="ITraceWriter"/> used by the serializer when writing trace messages.
/// </summary> /// </summary>
/// <value>The trace writer.</value> /// <value>The trace writer.</value>
public ITraceWriter? TraceWriter { get; set; } public ITraceWriter TraceWriter { get; set; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="SerializationBinder"/> used by the serializer when resolving type names. /// Gets or sets the <see cref="SerializationBinder"/> used by the serializer when resolving type names.
/// </summary> /// </summary>
/// <value>The binder.</value> /// <value>The binder.</value>
[Obsolete("Binder is obsolete. Use SerializationBinder instead.")] [Obsolete("Binder is obsolete. Use SerializationBinder instead.")]
public SerializationBinder? Binder public SerializationBinder Binder
{ {
get get
{ {
@ -290,13 +289,13 @@ namespace LC.Newtonsoft.Json
/// Gets or sets the <see cref="ISerializationBinder"/> used by the serializer when resolving type names. /// Gets or sets the <see cref="ISerializationBinder"/> used by the serializer when resolving type names.
/// </summary> /// </summary>
/// <value>The binder.</value> /// <value>The binder.</value>
public ISerializationBinder? SerializationBinder { get; set; } public ISerializationBinder SerializationBinder { get; set; }
/// <summary> /// <summary>
/// Gets or sets the error handler called during serialization and deserialization. /// Gets or sets the error handler called during serialization and deserialization.
/// </summary> /// </summary>
/// <value>The error handler called during serialization and deserialization.</value> /// <value>The error handler called during serialization and deserialization.</value>
public EventHandler<ErrorEventArgs>? Error { get; set; } public EventHandler<ErrorEventArgs> Error { get; set; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="StreamingContext"/> used by the serializer when invoking serialization callback methods. /// Gets or sets the <see cref="StreamingContext"/> used by the serializer when invoking serialization callback methods.
@ -326,11 +325,11 @@ namespace LC.Newtonsoft.Json
/// <summary> /// <summary>
/// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>. /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>.
/// A null value means there is no maximum. /// A null value means there is no maximum.
/// The default value is <c>128</c>. /// The default value is <c>null</c>.
/// </summary> /// </summary>
public int? MaxDepth public int? MaxDepth
{ {
get => _maxDepthSet ? _maxDepth : DefaultMaxDepth; get => _maxDepth;
set set
{ {
if (value <= 0) if (value <= 0)

View File

@ -34,7 +34,6 @@ using System.Numerics;
using System.Threading.Tasks; using System.Threading.Tasks;
using LC.Newtonsoft.Json.Serialization; using LC.Newtonsoft.Json.Serialization;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using System.Diagnostics;
namespace LC.Newtonsoft.Json namespace LC.Newtonsoft.Json
{ {
@ -111,8 +110,6 @@ namespace LC.Newtonsoft.Json
private async Task<bool> ParsePostValueAsync(bool ignoreComments, CancellationToken cancellationToken) private async Task<bool> ParsePostValueAsync(bool ignoreComments, CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
while (true) while (true)
{ {
char currentChar = _chars[_charPos]; char currentChar = _chars[_charPos];
@ -196,8 +193,6 @@ namespace LC.Newtonsoft.Json
private async Task<bool> ReadFromFinishedAsync(CancellationToken cancellationToken) private async Task<bool> ReadFromFinishedAsync(CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
if (await EnsureCharsAsync(0, false, cancellationToken).ConfigureAwait(false)) if (await EnsureCharsAsync(0, false, cancellationToken).ConfigureAwait(false))
{ {
await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false); await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false);
@ -227,8 +222,6 @@ namespace LC.Newtonsoft.Json
private async Task<int> ReadDataAsync(bool append, int charsRequired, CancellationToken cancellationToken) private async Task<int> ReadDataAsync(bool append, int charsRequired, CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
if (_isEndOfFile) if (_isEndOfFile)
{ {
return 0; return 0;
@ -251,8 +244,6 @@ namespace LC.Newtonsoft.Json
private async Task<bool> ParseValueAsync(CancellationToken cancellationToken) private async Task<bool> ParseValueAsync(CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
while (true) while (true)
{ {
char currentChar = _chars[_charPos]; char currentChar = _chars[_charPos];
@ -382,8 +373,6 @@ namespace LC.Newtonsoft.Json
private async Task ReadStringIntoBufferAsync(char quote, CancellationToken cancellationToken) private async Task ReadStringIntoBufferAsync(char quote, CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
int charPos = _charPos; int charPos = _charPos;
int initialPosition = _charPos; int initialPosition = _charPos;
int lastWritePosition = _charPos; int lastWritePosition = _charPos;
@ -600,8 +589,6 @@ namespace LC.Newtonsoft.Json
private async Task<bool> ParseObjectAsync(CancellationToken cancellationToken) private async Task<bool> ParseObjectAsync(CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
while (true) while (true)
{ {
char currentChar = _chars[_charPos]; char currentChar = _chars[_charPos];
@ -659,8 +646,6 @@ namespace LC.Newtonsoft.Json
private async Task ParseCommentAsync(bool setToken, CancellationToken cancellationToken) private async Task ParseCommentAsync(bool setToken, CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
// should have already parsed / character before reaching this method // should have already parsed / character before reaching this method
_charPos++; _charPos++;
@ -757,8 +742,6 @@ namespace LC.Newtonsoft.Json
private async Task EatWhitespaceAsync(CancellationToken cancellationToken) private async Task EatWhitespaceAsync(CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
while (true) while (true)
{ {
char currentChar = _chars[_charPos]; char currentChar = _chars[_charPos];
@ -815,8 +798,6 @@ namespace LC.Newtonsoft.Json
private async Task<bool> MatchValueWithTrailingSeparatorAsync(string value, CancellationToken cancellationToken) private async Task<bool> MatchValueWithTrailingSeparatorAsync(string value, CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
// will match value and then move to the next character, checking that it is a separator character // will match value and then move to the next character, checking that it is a separator character
if (!await MatchValueAsync(value, cancellationToken).ConfigureAwait(false)) if (!await MatchValueAsync(value, cancellationToken).ConfigureAwait(false))
{ {
@ -831,7 +812,7 @@ namespace LC.Newtonsoft.Json
return IsSeparator(_chars[_charPos]) || _chars[_charPos] == '\0'; return IsSeparator(_chars[_charPos]) || _chars[_charPos] == '\0';
} }
private async Task MatchAndSetAsync(string value, JsonToken newToken, object? tokenValue, CancellationToken cancellationToken) private async Task MatchAndSetAsync(string value, JsonToken newToken, object tokenValue, CancellationToken cancellationToken)
{ {
if (await MatchValueWithTrailingSeparatorAsync(value, cancellationToken).ConfigureAwait(false)) if (await MatchValueWithTrailingSeparatorAsync(value, cancellationToken).ConfigureAwait(false))
{ {
@ -860,8 +841,6 @@ namespace LC.Newtonsoft.Json
private async Task ParseConstructorAsync(CancellationToken cancellationToken) private async Task ParseConstructorAsync(CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
if (await MatchValueWithTrailingSeparatorAsync("new", cancellationToken).ConfigureAwait(false)) if (await MatchValueWithTrailingSeparatorAsync("new", cancellationToken).ConfigureAwait(false))
{ {
await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false); await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false);
@ -960,8 +939,6 @@ namespace LC.Newtonsoft.Json
private async Task ParseNumberAsync(ReadType readType, CancellationToken cancellationToken) private async Task ParseNumberAsync(ReadType readType, CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
ShiftBufferIfNeeded(); ShiftBufferIfNeeded();
char firstChar = _chars[_charPos]; char firstChar = _chars[_charPos];
@ -979,8 +956,6 @@ namespace LC.Newtonsoft.Json
private async Task<bool> ParsePropertyAsync(CancellationToken cancellationToken) private async Task<bool> ParsePropertyAsync(CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
char firstChar = _chars[_charPos]; char firstChar = _chars[_charPos];
char quoteChar; char quoteChar;
@ -1033,8 +1008,6 @@ namespace LC.Newtonsoft.Json
private async Task ReadNumberIntoBufferAsync(CancellationToken cancellationToken) private async Task ReadNumberIntoBufferAsync(CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
int charPos = _charPos; int charPos = _charPos;
while (true) while (true)
@ -1069,8 +1042,6 @@ namespace LC.Newtonsoft.Json
private async Task ParseUnquotedPropertyAsync(CancellationToken cancellationToken) private async Task ParseUnquotedPropertyAsync(CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
int initialPosition = _charPos; int initialPosition = _charPos;
// parse unquoted property name until whitespace or colon // parse unquoted property name until whitespace or colon
@ -1120,8 +1091,6 @@ namespace LC.Newtonsoft.Json
private async Task HandleNullAsync(CancellationToken cancellationToken) private async Task HandleNullAsync(CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
if (await EnsureCharsAsync(1, true, cancellationToken).ConfigureAwait(false)) if (await EnsureCharsAsync(1, true, cancellationToken).ConfigureAwait(false))
{ {
if (_chars[_charPos + 1] == 'u') if (_chars[_charPos + 1] == 'u')
@ -1140,8 +1109,6 @@ namespace LC.Newtonsoft.Json
private async Task ReadFinishedAsync(CancellationToken cancellationToken) private async Task ReadFinishedAsync(CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
if (await EnsureCharsAsync(0, false, cancellationToken).ConfigureAwait(false)) if (await EnsureCharsAsync(0, false, cancellationToken).ConfigureAwait(false))
{ {
await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false); await EatWhitespaceAsync(cancellationToken).ConfigureAwait(false);
@ -1164,10 +1131,9 @@ namespace LC.Newtonsoft.Json
SetToken(JsonToken.None); SetToken(JsonToken.None);
} }
private async Task<object?> ReadStringValueAsync(ReadType readType, CancellationToken cancellationToken) private async Task<object> ReadStringValueAsync(ReadType readType, CancellationToken cancellationToken)
{ {
EnsureBuffer(); EnsureBuffer();
MiscellaneousUtils.Assert(_chars != null);
switch (_currentState) switch (_currentState)
{ {
@ -1300,10 +1266,9 @@ namespace LC.Newtonsoft.Json
} }
} }
private async Task<object?> ReadNumberValueAsync(ReadType readType, CancellationToken cancellationToken) private async Task<object> ReadNumberValueAsync(ReadType readType, CancellationToken cancellationToken)
{ {
EnsureBuffer(); EnsureBuffer();
MiscellaneousUtils.Assert(_chars != null);
switch (_currentState) switch (_currentState)
{ {
@ -1430,7 +1395,6 @@ namespace LC.Newtonsoft.Json
internal async Task<bool?> DoReadAsBooleanAsync(CancellationToken cancellationToken) internal async Task<bool?> DoReadAsBooleanAsync(CancellationToken cancellationToken)
{ {
EnsureBuffer(); EnsureBuffer();
MiscellaneousUtils.Assert(_chars != null);
switch (_currentState) switch (_currentState)
{ {
@ -1558,16 +1522,14 @@ namespace LC.Newtonsoft.Json
/// property returns the <see cref="byte"/>[]. This result will be <c>null</c> at the end of an array.</returns> /// property returns the <see cref="byte"/>[]. This result will be <c>null</c> at the end of an array.</returns>
/// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will
/// execute synchronously, returning an already-completed task.</remarks> /// execute synchronously, returning an already-completed task.</remarks>
public override Task<byte[]?> ReadAsBytesAsync(CancellationToken cancellationToken = default) public override Task<byte[]> ReadAsBytesAsync(CancellationToken cancellationToken = default)
{ {
return _safeAsync ? DoReadAsBytesAsync(cancellationToken) : base.ReadAsBytesAsync(cancellationToken); return _safeAsync ? DoReadAsBytesAsync(cancellationToken) : base.ReadAsBytesAsync(cancellationToken);
} }
internal async Task<byte[]?> DoReadAsBytesAsync(CancellationToken cancellationToken) internal async Task<byte[]> DoReadAsBytesAsync(CancellationToken cancellationToken)
{ {
EnsureBuffer(); EnsureBuffer();
MiscellaneousUtils.Assert(_chars != null);
bool isWrapped = false; bool isWrapped = false;
switch (_currentState) switch (_currentState)
@ -1601,7 +1563,7 @@ namespace LC.Newtonsoft.Json
case '"': case '"':
case '\'': case '\'':
await ParseStringAsync(currentChar, ReadType.ReadAsBytes, cancellationToken).ConfigureAwait(false); await ParseStringAsync(currentChar, ReadType.ReadAsBytes, cancellationToken).ConfigureAwait(false);
byte[]? data = (byte[]?)Value; byte[] data = (byte[])Value;
if (isWrapped) if (isWrapped)
{ {
await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(false); await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(false);
@ -1791,14 +1753,14 @@ namespace LC.Newtonsoft.Json
/// property returns the <see cref="string"/>. This result will be <c>null</c> at the end of an array.</returns> /// property returns the <see cref="string"/>. This result will be <c>null</c> at the end of an array.</returns>
/// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will
/// execute synchronously, returning an already-completed task.</remarks> /// execute synchronously, returning an already-completed task.</remarks>
public override Task<string?> ReadAsStringAsync(CancellationToken cancellationToken = default) public override Task<string> ReadAsStringAsync(CancellationToken cancellationToken = default)
{ {
return _safeAsync ? DoReadAsStringAsync(cancellationToken) : base.ReadAsStringAsync(cancellationToken); return _safeAsync ? DoReadAsStringAsync(cancellationToken) : base.ReadAsStringAsync(cancellationToken);
} }
internal async Task<string?> DoReadAsStringAsync(CancellationToken cancellationToken) internal async Task<string> DoReadAsStringAsync(CancellationToken cancellationToken)
{ {
return (string?)await ReadStringValueAsync(ReadType.ReadAsString, cancellationToken).ConfigureAwait(false); return (string)await ReadStringValueAsync(ReadType.ReadAsString, cancellationToken).ConfigureAwait(false);
} }
} }
} }

View File

@ -27,7 +27,6 @@ using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.IO; using System.IO;
using System.Globalization; using System.Globalization;
using System.Diagnostics;
#if HAVE_BIG_INTEGER #if HAVE_BIG_INTEGER
using System.Numerics; using System.Numerics;
#endif #endif
@ -67,7 +66,7 @@ namespace LC.Newtonsoft.Json
#endif #endif
private readonly TextReader _reader; private readonly TextReader _reader;
private char[]? _chars; private char[] _chars;
private int _charsUsed; private int _charsUsed;
private int _charPos; private int _charPos;
private int _lineStartPos; private int _lineStartPos;
@ -75,7 +74,7 @@ namespace LC.Newtonsoft.Json
private bool _isEndOfFile; private bool _isEndOfFile;
private StringBuffer _stringBuffer; private StringBuffer _stringBuffer;
private StringReference _stringReference; private StringReference _stringReference;
private IArrayPool<char>? _arrayPool; private IArrayPool<char> _arrayPool;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="JsonTextReader"/> class with the specified <see cref="TextReader"/>. /// Initializes a new instance of the <see cref="JsonTextReader"/> class with the specified <see cref="TextReader"/>.
@ -97,7 +96,7 @@ namespace LC.Newtonsoft.Json
} }
#if DEBUG #if DEBUG
internal char[]? CharBuffer internal char[] CharBuffer
{ {
get => _chars; get => _chars;
set => _chars = value; set => _chars = value;
@ -109,12 +108,12 @@ namespace LC.Newtonsoft.Json
/// <summary> /// <summary>
/// Gets or sets the reader's property name table. /// Gets or sets the reader's property name table.
/// </summary> /// </summary>
public JsonNameTable? PropertyNameTable { get; set; } public JsonNameTable PropertyNameTable { get; set; }
/// <summary> /// <summary>
/// Gets or sets the reader's character buffer pool. /// Gets or sets the reader's character buffer pool.
/// </summary> /// </summary>
public IArrayPool<char>? ArrayPool public IArrayPool<char> ArrayPool
{ {
get => _arrayPool; get => _arrayPool;
set set
@ -138,8 +137,6 @@ namespace LC.Newtonsoft.Json
private void SetNewLine(bool hasNextChar) private void SetNewLine(bool hasNextChar)
{ {
MiscellaneousUtils.Assert(_chars != null);
if (hasNextChar && _chars[_charPos] == StringUtils.LineFeed) if (hasNextChar && _chars[_charPos] == StringUtils.LineFeed)
{ {
_charPos++; _charPos++;
@ -252,8 +249,6 @@ namespace LC.Newtonsoft.Json
private void ShiftBufferIfNeeded() private void ShiftBufferIfNeeded()
{ {
MiscellaneousUtils.Assert(_chars != null);
// once in the last 10% of the buffer, or buffer is already very large then // once in the last 10% of the buffer, or buffer is already very large then
// shift the remaining content to the start to avoid unnecessarily increasing // shift the remaining content to the start to avoid unnecessarily increasing
// the buffer size when reading numbers/strings // the buffer size when reading numbers/strings
@ -280,8 +275,6 @@ namespace LC.Newtonsoft.Json
private void PrepareBufferForReadData(bool append, int charsRequired) private void PrepareBufferForReadData(bool append, int charsRequired)
{ {
MiscellaneousUtils.Assert(_chars != null);
// char buffer is full // char buffer is full
if (_charsUsed + charsRequired >= _chars.Length - 1) if (_charsUsed + charsRequired >= _chars.Length - 1)
{ {
@ -345,7 +338,6 @@ namespace LC.Newtonsoft.Json
} }
PrepareBufferForReadData(append, charsRequired); PrepareBufferForReadData(append, charsRequired);
MiscellaneousUtils.Assert(_chars != null);
int attemptCharReadCount = _chars.Length - _charsUsed - 1; int attemptCharReadCount = _chars.Length - _charsUsed - 1;
@ -414,7 +406,6 @@ namespace LC.Newtonsoft.Json
public override bool Read() public override bool Read()
{ {
EnsureBuffer(); EnsureBuffer();
MiscellaneousUtils.Assert(_chars != null);
while (true) while (true)
{ {
@ -485,20 +476,18 @@ namespace LC.Newtonsoft.Json
/// Reads the next JSON token from the underlying <see cref="TextReader"/> as a <see cref="String"/>. /// Reads the next JSON token from the underlying <see cref="TextReader"/> as a <see cref="String"/>.
/// </summary> /// </summary>
/// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns> /// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
public override string? ReadAsString() public override string ReadAsString()
{ {
return (string?)ReadStringValue(ReadType.ReadAsString); return (string)ReadStringValue(ReadType.ReadAsString);
} }
/// <summary> /// <summary>
/// Reads the next JSON token from the underlying <see cref="TextReader"/> as a <see cref="Byte"/>[]. /// Reads the next JSON token from the underlying <see cref="TextReader"/> as a <see cref="Byte"/>[].
/// </summary> /// </summary>
/// <returns>A <see cref="Byte"/>[] or <c>null</c> if the next JSON token is null. This method will return <c>null</c> at the end of an array.</returns> /// <returns>A <see cref="Byte"/>[] or <c>null</c> if the next JSON token is null. This method will return <c>null</c> at the end of an array.</returns>
public override byte[]? ReadAsBytes() public override byte[] ReadAsBytes()
{ {
EnsureBuffer(); EnsureBuffer();
MiscellaneousUtils.Assert(_chars != null);
bool isWrapped = false; bool isWrapped = false;
switch (_currentState) switch (_currentState)
@ -531,7 +520,7 @@ namespace LC.Newtonsoft.Json
case '"': case '"':
case '\'': case '\'':
ParseString(currentChar, ReadType.ReadAsBytes); ParseString(currentChar, ReadType.ReadAsBytes);
byte[]? data = (byte[]?)Value; byte[] data = (byte[])Value;
if (isWrapped) if (isWrapped)
{ {
ReaderReadAndAssert(); ReaderReadAndAssert();
@ -600,10 +589,9 @@ namespace LC.Newtonsoft.Json
} }
} }
private object? ReadStringValue(ReadType readType) private object ReadStringValue(ReadType readType)
{ {
EnsureBuffer(); EnsureBuffer();
MiscellaneousUtils.Assert(_chars != null);
switch (_currentState) switch (_currentState)
{ {
@ -730,7 +718,7 @@ namespace LC.Newtonsoft.Json
} }
} }
private object? FinishReadQuotedStringValue(ReadType readType) private object FinishReadQuotedStringValue(ReadType readType)
{ {
switch (readType) switch (readType)
{ {
@ -743,7 +731,7 @@ namespace LC.Newtonsoft.Json
return time; return time;
} }
return ReadDateTimeString((string?)Value); return ReadDateTimeString((string)Value);
#if HAVE_DATE_TIME_OFFSET #if HAVE_DATE_TIME_OFFSET
case ReadType.ReadAsDateTimeOffset: case ReadType.ReadAsDateTimeOffset:
if (Value is DateTimeOffset offset) if (Value is DateTimeOffset offset)
@ -751,7 +739,7 @@ namespace LC.Newtonsoft.Json
return offset; return offset;
} }
return ReadDateTimeOffsetString((string?)Value); return ReadDateTimeOffsetString((string)Value);
#endif #endif
default: default:
throw new ArgumentOutOfRangeException(nameof(readType)); throw new ArgumentOutOfRangeException(nameof(readType));
@ -770,7 +758,6 @@ namespace LC.Newtonsoft.Json
public override bool? ReadAsBoolean() public override bool? ReadAsBoolean()
{ {
EnsureBuffer(); EnsureBuffer();
MiscellaneousUtils.Assert(_chars != null);
switch (_currentState) switch (_currentState)
{ {
@ -905,10 +892,9 @@ namespace LC.Newtonsoft.Json
SetStateBasedOnCurrent(); SetStateBasedOnCurrent();
} }
private object? ReadNumberValue(ReadType readType) private object ReadNumberValue(ReadType readType)
{ {
EnsureBuffer(); EnsureBuffer();
MiscellaneousUtils.Assert(_chars != null);
switch (_currentState) switch (_currentState)
{ {
@ -1016,7 +1002,7 @@ namespace LC.Newtonsoft.Json
} }
} }
private object? FinishReadQuotedNumber(ReadType readType) private object FinishReadQuotedNumber(ReadType readType)
{ {
switch (readType) switch (readType)
{ {
@ -1062,8 +1048,6 @@ namespace LC.Newtonsoft.Json
private void HandleNull() private void HandleNull()
{ {
MiscellaneousUtils.Assert(_chars != null);
if (EnsureChars(1, true)) if (EnsureChars(1, true))
{ {
char next = _chars[_charPos + 1]; char next = _chars[_charPos + 1];
@ -1084,8 +1068,6 @@ namespace LC.Newtonsoft.Json
private void ReadFinished() private void ReadFinished()
{ {
MiscellaneousUtils.Assert(_chars != null);
if (EnsureChars(0, false)) if (EnsureChars(0, false))
{ {
EatWhitespace(); EatWhitespace();
@ -1135,8 +1117,6 @@ namespace LC.Newtonsoft.Json
private void ReadStringIntoBuffer(char quote) private void ReadStringIntoBuffer(char quote)
{ {
MiscellaneousUtils.Assert(_chars != null);
int charPos = _charPos; int charPos = _charPos;
int initialPosition = _charPos; int initialPosition = _charPos;
int lastWritePosition = _charPos; int lastWritePosition = _charPos;
@ -1290,8 +1270,6 @@ namespace LC.Newtonsoft.Json
private void FinishReadStringIntoBuffer(int charPos, int initialPosition, int lastWritePosition) private void FinishReadStringIntoBuffer(int charPos, int initialPosition, int lastWritePosition)
{ {
MiscellaneousUtils.Assert(_chars != null);
if (initialPosition == lastWritePosition) if (initialPosition == lastWritePosition)
{ {
_stringReference = new StringReference(_chars, initialPosition, charPos - initialPosition); _stringReference = new StringReference(_chars, initialPosition, charPos - initialPosition);
@ -1305,7 +1283,7 @@ namespace LC.Newtonsoft.Json
_stringBuffer.Append(_arrayPool, _chars, lastWritePosition, charPos - lastWritePosition); _stringBuffer.Append(_arrayPool, _chars, lastWritePosition, charPos - lastWritePosition);
} }
_stringReference = new StringReference(_stringBuffer.InternalBuffer!, 0, _stringBuffer.Position); _stringReference = new StringReference(_stringBuffer.InternalBuffer, 0, _stringBuffer.Position);
} }
_charPos = charPos + 1; _charPos = charPos + 1;
@ -1313,8 +1291,6 @@ namespace LC.Newtonsoft.Json
private void WriteCharToBuffer(char writeChar, int lastWritePosition, int writeToPosition) private void WriteCharToBuffer(char writeChar, int lastWritePosition, int writeToPosition)
{ {
MiscellaneousUtils.Assert(_chars != null);
if (writeToPosition > lastWritePosition) if (writeToPosition > lastWritePosition)
{ {
_stringBuffer.Append(_arrayPool, _chars, lastWritePosition, writeToPosition - lastWritePosition); _stringBuffer.Append(_arrayPool, _chars, lastWritePosition, writeToPosition - lastWritePosition);
@ -1325,8 +1301,6 @@ namespace LC.Newtonsoft.Json
private char ConvertUnicode(bool enoughChars) private char ConvertUnicode(bool enoughChars)
{ {
MiscellaneousUtils.Assert(_chars != null);
if (enoughChars) if (enoughChars)
{ {
if (ConvertUtils.TryHexTextToInt(_chars, _charPos, _charPos + 4, out int value)) if (ConvertUtils.TryHexTextToInt(_chars, _charPos, _charPos + 4, out int value))
@ -1353,8 +1327,6 @@ namespace LC.Newtonsoft.Json
private void ReadNumberIntoBuffer() private void ReadNumberIntoBuffer()
{ {
MiscellaneousUtils.Assert(_chars != null);
int charPos = _charPos; int charPos = _charPos;
while (true) while (true)
@ -1439,8 +1411,6 @@ namespace LC.Newtonsoft.Json
private bool ParsePostValue(bool ignoreComments) private bool ParsePostValue(bool ignoreComments)
{ {
MiscellaneousUtils.Assert(_chars != null);
while (true) while (true)
{ {
char currentChar = _chars[_charPos]; char currentChar = _chars[_charPos];
@ -1521,8 +1491,6 @@ namespace LC.Newtonsoft.Json
private bool ParseObject() private bool ParseObject()
{ {
MiscellaneousUtils.Assert(_chars != null);
while (true) while (true)
{ {
char currentChar = _chars[_charPos]; char currentChar = _chars[_charPos];
@ -1577,8 +1545,6 @@ namespace LC.Newtonsoft.Json
private bool ParseProperty() private bool ParseProperty()
{ {
MiscellaneousUtils.Assert(_chars != null);
char firstChar = _chars[_charPos]; char firstChar = _chars[_charPos];
char quoteChar; char quoteChar;
@ -1600,7 +1566,7 @@ namespace LC.Newtonsoft.Json
throw JsonReaderException.Create(this, "Invalid property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); throw JsonReaderException.Create(this, "Invalid property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
} }
string? propertyName; string propertyName;
if (PropertyNameTable != null) if (PropertyNameTable != null)
{ {
@ -1640,8 +1606,6 @@ namespace LC.Newtonsoft.Json
private void ParseUnquotedProperty() private void ParseUnquotedProperty()
{ {
MiscellaneousUtils.Assert(_chars != null);
int initialPosition = _charPos; int initialPosition = _charPos;
// parse unquoted property name until whitespace or colon // parse unquoted property name until whitespace or colon
@ -1673,8 +1637,6 @@ namespace LC.Newtonsoft.Json
private bool ReadUnquotedPropertyReportIfDone(char currentChar, int initialPosition) private bool ReadUnquotedPropertyReportIfDone(char currentChar, int initialPosition)
{ {
MiscellaneousUtils.Assert(_chars != null);
if (ValidIdentifierChar(currentChar)) if (ValidIdentifierChar(currentChar))
{ {
_charPos++; _charPos++;
@ -1692,8 +1654,6 @@ namespace LC.Newtonsoft.Json
private bool ParseValue() private bool ParseValue()
{ {
MiscellaneousUtils.Assert(_chars != null);
while (true) while (true)
{ {
char currentChar = _chars[_charPos]; char currentChar = _chars[_charPos];
@ -1834,8 +1794,6 @@ namespace LC.Newtonsoft.Json
private void EatWhitespace() private void EatWhitespace()
{ {
MiscellaneousUtils.Assert(_chars != null);
while (true) while (true)
{ {
char currentChar = _chars[_charPos]; char currentChar = _chars[_charPos];
@ -1877,8 +1835,6 @@ namespace LC.Newtonsoft.Json
private void ParseConstructor() private void ParseConstructor()
{ {
MiscellaneousUtils.Assert(_chars != null);
if (MatchValueWithTrailingSeparator("new")) if (MatchValueWithTrailingSeparator("new"))
{ {
EatWhitespace(); EatWhitespace();
@ -1963,7 +1919,6 @@ namespace LC.Newtonsoft.Json
private void ParseNumber(ReadType readType) private void ParseNumber(ReadType readType)
{ {
ShiftBufferIfNeeded(); ShiftBufferIfNeeded();
MiscellaneousUtils.Assert(_chars != null);
char firstChar = _chars[_charPos]; char firstChar = _chars[_charPos];
int initialPosition = _charPos; int initialPosition = _charPos;
@ -1974,9 +1929,7 @@ namespace LC.Newtonsoft.Json
} }
private void ParseReadNumber(ReadType readType, char firstChar, int initialPosition) private void ParseReadNumber(ReadType readType, char firstChar, int initialPosition)
{ {
MiscellaneousUtils.Assert(_chars != null);
// set state to PostValue now so that if there is an error parsing the number then the reader can continue // set state to PostValue now so that if there is an error parsing the number then the reader can continue
SetPostValueState(true); SetPostValueState(true);
@ -2237,7 +2190,7 @@ namespace LC.Newtonsoft.Json
SetToken(numberType, numberValue, false); SetToken(numberType, numberValue, false);
} }
private JsonReaderException ThrowReaderError(string message, Exception? ex = null) private JsonReaderException ThrowReaderError(string message, Exception ex = null)
{ {
SetToken(JsonToken.Undefined, null, false); SetToken(JsonToken.Undefined, null, false);
return JsonReaderException.Create(this, message, ex); return JsonReaderException.Create(this, message, ex);
@ -2257,8 +2210,6 @@ namespace LC.Newtonsoft.Json
private void ParseComment(bool setToken) private void ParseComment(bool setToken)
{ {
MiscellaneousUtils.Assert(_chars != null);
// should have already parsed / character before reaching this method // should have already parsed / character before reaching this method
_charPos++; _charPos++;
@ -2364,8 +2315,6 @@ namespace LC.Newtonsoft.Json
private bool MatchValue(bool enoughChars, string value) private bool MatchValue(bool enoughChars, string value)
{ {
MiscellaneousUtils.Assert(_chars != null);
if (!enoughChars) if (!enoughChars)
{ {
_charPos = _charsUsed; _charPos = _charsUsed;
@ -2388,8 +2337,6 @@ namespace LC.Newtonsoft.Json
private bool MatchValueWithTrailingSeparator(string value) private bool MatchValueWithTrailingSeparator(string value)
{ {
MiscellaneousUtils.Assert(_chars != null);
// will match value and then move to the next character, checking that it is a separator character // will match value and then move to the next character, checking that it is a separator character
bool match = MatchValue(value); bool match = MatchValue(value);
@ -2408,8 +2355,6 @@ namespace LC.Newtonsoft.Json
private bool IsSeparator(char c) private bool IsSeparator(char c)
{ {
MiscellaneousUtils.Assert(_chars != null);
switch (c) switch (c)
{ {
case '}': case '}':

View File

@ -33,7 +33,6 @@ using System.Numerics;
#endif #endif
using System.Threading.Tasks; using System.Threading.Tasks;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using System.Diagnostics;
namespace LC.Newtonsoft.Json namespace LC.Newtonsoft.Json
{ {
@ -165,7 +164,6 @@ namespace LC.Newtonsoft.Json
int currentIndentCount = Top * _indentation; int currentIndentCount = Top * _indentation;
int newLineLen = SetIndentChars(); int newLineLen = SetIndentChars();
MiscellaneousUtils.Assert(_indentChars != null);
if (currentIndentCount <= IndentCharBufferSize) if (currentIndentCount <= IndentCharBufferSize)
{ {
@ -177,8 +175,6 @@ namespace LC.Newtonsoft.Json
private async Task WriteIndentAsync(int currentIndentCount, int newLineLen, CancellationToken cancellationToken) private async Task WriteIndentAsync(int currentIndentCount, int newLineLen, CancellationToken cancellationToken)
{ {
MiscellaneousUtils.Assert(_indentChars != null);
await _writer.WriteAsync(_indentChars, 0, newLineLen + Math.Min(currentIndentCount, IndentCharBufferSize), cancellationToken).ConfigureAwait(false); await _writer.WriteAsync(_indentChars, 0, newLineLen + Math.Min(currentIndentCount, IndentCharBufferSize), cancellationToken).ConfigureAwait(false);
while ((currentIndentCount -= IndentCharBufferSize) > 0) while ((currentIndentCount -= IndentCharBufferSize) > 0)
@ -229,12 +225,12 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will
/// execute synchronously, returning an already-completed task.</remarks> /// execute synchronously, returning an already-completed task.</remarks>
public override Task WriteRawAsync(string? json, CancellationToken cancellationToken = default) public override Task WriteRawAsync(string json, CancellationToken cancellationToken = default)
{ {
return _safeAsync ? DoWriteRawAsync(json, cancellationToken) : base.WriteRawAsync(json, cancellationToken); return _safeAsync ? DoWriteRawAsync(json, cancellationToken) : base.WriteRawAsync(json, cancellationToken);
} }
internal Task DoWriteRawAsync(string? json, CancellationToken cancellationToken) internal Task DoWriteRawAsync(string json, CancellationToken cancellationToken)
{ {
return _writer.WriteAsync(json, cancellationToken); return _writer.WriteAsync(json, cancellationToken);
} }
@ -264,7 +260,7 @@ namespace LC.Newtonsoft.Json
} }
int length = WriteNumberToBuffer(uvalue, negative); int length = WriteNumberToBuffer(uvalue, negative);
return _writer.WriteAsync(_writeBuffer!, 0, length, cancellationToken); return _writer.WriteAsync(_writeBuffer, 0, length, cancellationToken);
} }
private Task WriteIntegerValueAsync(ulong uvalue, bool negative, CancellationToken cancellationToken) private Task WriteIntegerValueAsync(ulong uvalue, bool negative, CancellationToken cancellationToken)
@ -302,7 +298,7 @@ namespace LC.Newtonsoft.Json
private Task WriteEscapedStringAsync(string value, bool quote, CancellationToken cancellationToken) private Task WriteEscapedStringAsync(string value, bool quote, CancellationToken cancellationToken)
{ {
return JavaScriptUtils.WriteEscapedJavaScriptStringAsync(_writer, value, _quoteChar, quote, _charEscapeFlags!, StringEscapeHandling, this, _writeBuffer!, cancellationToken); return JavaScriptUtils.WriteEscapedJavaScriptStringAsync(_writer, value, _quoteChar, quote, _charEscapeFlags, StringEscapeHandling, this, _writeBuffer, cancellationToken);
} }
/// <summary> /// <summary>
@ -589,7 +585,7 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will
/// execute synchronously, returning an already-completed task.</remarks> /// execute synchronously, returning an already-completed task.</remarks>
public override Task WriteValueAsync(byte[]? value, CancellationToken cancellationToken = default) public override Task WriteValueAsync(byte[] value, CancellationToken cancellationToken = default)
{ {
return _safeAsync ? (value == null ? WriteNullAsync(cancellationToken) : WriteValueNonNullAsync(value, cancellationToken)) : base.WriteValueAsync(value, cancellationToken); return _safeAsync ? (value == null ? WriteNullAsync(cancellationToken) : WriteValueNonNullAsync(value, cancellationToken)) : base.WriteValueAsync(value, cancellationToken);
} }
@ -657,11 +653,11 @@ namespace LC.Newtonsoft.Json
await InternalWriteValueAsync(JsonToken.Date, cancellationToken).ConfigureAwait(false); await InternalWriteValueAsync(JsonToken.Date, cancellationToken).ConfigureAwait(false);
value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling); value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling);
if (StringUtils.IsNullOrEmpty(DateFormatString)) if (string.IsNullOrEmpty(DateFormatString))
{ {
int length = WriteValueToBuffer(value); int length = WriteValueToBuffer(value);
await _writer.WriteAsync(_writeBuffer!, 0, length, cancellationToken).ConfigureAwait(false); await _writer.WriteAsync(_writeBuffer, 0, length, cancellationToken).ConfigureAwait(false);
} }
else else
{ {
@ -706,11 +702,11 @@ namespace LC.Newtonsoft.Json
{ {
await InternalWriteValueAsync(JsonToken.Date, cancellationToken).ConfigureAwait(false); await InternalWriteValueAsync(JsonToken.Date, cancellationToken).ConfigureAwait(false);
if (StringUtils.IsNullOrEmpty(DateFormatString)) if (string.IsNullOrEmpty(DateFormatString))
{ {
int length = WriteValueToBuffer(value); int length = WriteValueToBuffer(value);
await _writer.WriteAsync(_writeBuffer!, 0, length, cancellationToken).ConfigureAwait(false); await _writer.WriteAsync(_writeBuffer, 0, length, cancellationToken).ConfigureAwait(false);
} }
else else
{ {
@ -957,7 +953,7 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will
/// execute synchronously, returning an already-completed task.</remarks> /// execute synchronously, returning an already-completed task.</remarks>
public override Task WriteValueAsync(object? value, CancellationToken cancellationToken = default) public override Task WriteValueAsync(object value, CancellationToken cancellationToken = default)
{ {
if (_safeAsync) if (_safeAsync)
{ {
@ -1050,12 +1046,12 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will
/// execute synchronously, returning an already-completed task.</remarks> /// execute synchronously, returning an already-completed task.</remarks>
public override Task WriteValueAsync(string? value, CancellationToken cancellationToken = default) public override Task WriteValueAsync(string value, CancellationToken cancellationToken = default)
{ {
return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken); return _safeAsync ? DoWriteValueAsync(value, cancellationToken) : base.WriteValueAsync(value, cancellationToken);
} }
internal Task DoWriteValueAsync(string? value, CancellationToken cancellationToken) internal Task DoWriteValueAsync(string value, CancellationToken cancellationToken)
{ {
Task task = InternalWriteValueAsync(JsonToken.String, cancellationToken); Task task = InternalWriteValueAsync(JsonToken.String, cancellationToken);
if (task.IsCompletedSucessfully()) if (task.IsCompletedSucessfully())
@ -1066,7 +1062,7 @@ namespace LC.Newtonsoft.Json
return DoWriteValueAsync(task, value, cancellationToken); return DoWriteValueAsync(task, value, cancellationToken);
} }
private async Task DoWriteValueAsync(Task task, string? value, CancellationToken cancellationToken) private async Task DoWriteValueAsync(Task task, string value, CancellationToken cancellationToken)
{ {
await task.ConfigureAwait(false); await task.ConfigureAwait(false);
await (value == null ? _writer.WriteAsync(JsonConvert.Null, cancellationToken) : WriteEscapedStringAsync(value, true, cancellationToken)).ConfigureAwait(false); await (value == null ? _writer.WriteAsync(JsonConvert.Null, cancellationToken) : WriteEscapedStringAsync(value, true, cancellationToken)).ConfigureAwait(false);
@ -1185,7 +1181,7 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will
/// execute synchronously, returning an already-completed task.</remarks> /// execute synchronously, returning an already-completed task.</remarks>
public override Task WriteValueAsync(Uri? value, CancellationToken cancellationToken = default) public override Task WriteValueAsync(Uri value, CancellationToken cancellationToken = default)
{ {
return _safeAsync ? (value == null ? WriteNullAsync(cancellationToken) : WriteValueNotNullAsync(value, cancellationToken)) : base.WriteValueAsync(value, cancellationToken); return _safeAsync ? (value == null ? WriteNullAsync(cancellationToken) : WriteValueNotNullAsync(value, cancellationToken)) : base.WriteValueAsync(value, cancellationToken);
} }
@ -1248,16 +1244,16 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will
/// execute synchronously, returning an already-completed task.</remarks> /// execute synchronously, returning an already-completed task.</remarks>
public override Task WriteCommentAsync(string? text, CancellationToken cancellationToken = default) public override Task WriteCommentAsync(string text, CancellationToken cancellationToken = default)
{ {
return _safeAsync ? DoWriteCommentAsync(text, cancellationToken) : base.WriteCommentAsync(text, cancellationToken); return _safeAsync ? DoWriteCommentAsync(text, cancellationToken) : base.WriteCommentAsync(text, cancellationToken);
} }
internal async Task DoWriteCommentAsync(string? text, CancellationToken cancellationToken) internal async Task DoWriteCommentAsync(string text, CancellationToken cancellationToken)
{ {
await InternalWriteCommentAsync(cancellationToken).ConfigureAwait(false); await InternalWriteCommentAsync(cancellationToken).ConfigureAwait(false);
await _writer.WriteAsync("/*", cancellationToken).ConfigureAwait(false); await _writer.WriteAsync("/*", cancellationToken).ConfigureAwait(false);
await _writer.WriteAsync(text ?? string.Empty, cancellationToken).ConfigureAwait(false); await _writer.WriteAsync(text, cancellationToken).ConfigureAwait(false);
await _writer.WriteAsync("*/", cancellationToken).ConfigureAwait(false); await _writer.WriteAsync("*/", cancellationToken).ConfigureAwait(false);
} }
@ -1305,12 +1301,12 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will /// <remarks>Derived classes must override this method to get asynchronous behaviour. Otherwise it will
/// execute synchronously, returning an already-completed task.</remarks> /// execute synchronously, returning an already-completed task.</remarks>
public override Task WriteRawValueAsync(string? json, CancellationToken cancellationToken = default) public override Task WriteRawValueAsync(string json, CancellationToken cancellationToken = default)
{ {
return _safeAsync ? DoWriteRawValueAsync(json, cancellationToken) : base.WriteRawValueAsync(json, cancellationToken); return _safeAsync ? DoWriteRawValueAsync(json, cancellationToken) : base.WriteRawValueAsync(json, cancellationToken);
} }
internal Task DoWriteRawValueAsync(string? json, CancellationToken cancellationToken) internal Task DoWriteRawValueAsync(string json, CancellationToken cancellationToken)
{ {
UpdateScopeWithFinishedValue(); UpdateScopeWithFinishedValue();
Task task = AutoCompleteAsync(JsonToken.Undefined, cancellationToken); Task task = AutoCompleteAsync(JsonToken.Undefined, cancellationToken);
@ -1322,7 +1318,7 @@ namespace LC.Newtonsoft.Json
return DoWriteRawValueAsync(task, json, cancellationToken); return DoWriteRawValueAsync(task, json, cancellationToken);
} }
private async Task DoWriteRawValueAsync(Task task, string? json, CancellationToken cancellationToken) private async Task DoWriteRawValueAsync(Task task, string json, CancellationToken cancellationToken)
{ {
await task.ConfigureAwait(false); await task.ConfigureAwait(false);
await WriteRawAsync(json, cancellationToken).ConfigureAwait(false); await WriteRawAsync(json, cancellationToken).ConfigureAwait(false);
@ -1335,7 +1331,7 @@ namespace LC.Newtonsoft.Json
length = 35; length = 35;
} }
char[]? buffer = _writeBuffer; char[] buffer = _writeBuffer;
if (buffer == null) if (buffer == null)
{ {
return _writeBuffer = BufferUtils.RentBuffer(_arrayPool, length); return _writeBuffer = BufferUtils.RentBuffer(_arrayPool, length);

View File

@ -33,7 +33,6 @@ using System.Text;
using System.IO; using System.IO;
using System.Xml; using System.Xml;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using System.Diagnostics;
namespace LC.Newtonsoft.Json namespace LC.Newtonsoft.Json
{ {
@ -44,15 +43,15 @@ namespace LC.Newtonsoft.Json
{ {
private const int IndentCharBufferSize = 12; private const int IndentCharBufferSize = 12;
private readonly TextWriter _writer; private readonly TextWriter _writer;
private Base64Encoder? _base64Encoder; private Base64Encoder _base64Encoder;
private char _indentChar; private char _indentChar;
private int _indentation; private int _indentation;
private char _quoteChar; private char _quoteChar;
private bool _quoteName; private bool _quoteName;
private bool[]? _charEscapeFlags; private bool[] _charEscapeFlags;
private char[]? _writeBuffer; private char[] _writeBuffer;
private IArrayPool<char>? _arrayPool; private IArrayPool<char> _arrayPool;
private char[]? _indentChars; private char[] _indentChars;
private Base64Encoder Base64Encoder private Base64Encoder Base64Encoder
{ {
@ -70,7 +69,7 @@ namespace LC.Newtonsoft.Json
/// <summary> /// <summary>
/// Gets or sets the writer's character array pool. /// Gets or sets the writer's character array pool.
/// </summary> /// </summary>
public IArrayPool<char>? ArrayPool public IArrayPool<char> ArrayPool
{ {
get => _arrayPool; get => _arrayPool;
set set
@ -343,7 +342,7 @@ namespace LC.Newtonsoft.Json
{ {
for (int i = 0; i != newLineLen; ++i) for (int i = 0; i != newLineLen; ++i)
{ {
if (writerNewLine[i] != _indentChars![i]) if (writerNewLine[i] != _indentChars[i])
{ {
match = false; match = false;
break; break;
@ -388,7 +387,7 @@ namespace LC.Newtonsoft.Json
/// An error will raised if the value cannot be written as a single JSON token. /// An error will raised if the value cannot be written as a single JSON token.
/// </summary> /// </summary>
/// <param name="value">The <see cref="Object"/> value to write.</param> /// <param name="value">The <see cref="Object"/> value to write.</param>
public override void WriteValue(object? value) public override void WriteValue(object value)
{ {
#if HAVE_BIG_INTEGER #if HAVE_BIG_INTEGER
if (value is BigInteger i) if (value is BigInteger i)
@ -425,7 +424,7 @@ namespace LC.Newtonsoft.Json
/// Writes raw JSON. /// Writes raw JSON.
/// </summary> /// </summary>
/// <param name="json">The raw JSON to write.</param> /// <param name="json">The raw JSON to write.</param>
public override void WriteRaw(string? json) public override void WriteRaw(string json)
{ {
InternalWriteRaw(); InternalWriteRaw();
@ -436,7 +435,7 @@ namespace LC.Newtonsoft.Json
/// Writes a <see cref="String"/> value. /// Writes a <see cref="String"/> value.
/// </summary> /// </summary>
/// <param name="value">The <see cref="String"/> value to write.</param> /// <param name="value">The <see cref="String"/> value to write.</param>
public override void WriteValue(string? value) public override void WriteValue(string value)
{ {
InternalWriteValue(JsonToken.String); InternalWriteValue(JsonToken.String);
@ -453,7 +452,7 @@ namespace LC.Newtonsoft.Json
private void WriteEscapedString(string value, bool quote) private void WriteEscapedString(string value, bool quote)
{ {
EnsureWriteBuffer(); EnsureWriteBuffer();
JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, quote, _charEscapeFlags!, StringEscapeHandling, _arrayPool, ref _writeBuffer); JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, quote, _charEscapeFlags, StringEscapeHandling, _arrayPool, ref _writeBuffer);
} }
/// <summary> /// <summary>
@ -633,7 +632,7 @@ namespace LC.Newtonsoft.Json
InternalWriteValue(JsonToken.Date); InternalWriteValue(JsonToken.Date);
value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling); value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling);
if (StringUtils.IsNullOrEmpty(DateFormatString)) if (string.IsNullOrEmpty(DateFormatString))
{ {
int length = WriteValueToBuffer(value); int length = WriteValueToBuffer(value);
@ -650,7 +649,6 @@ namespace LC.Newtonsoft.Json
private int WriteValueToBuffer(DateTime value) private int WriteValueToBuffer(DateTime value)
{ {
EnsureWriteBuffer(); EnsureWriteBuffer();
MiscellaneousUtils.Assert(_writeBuffer != null);
int pos = 0; int pos = 0;
_writeBuffer[pos++] = _quoteChar; _writeBuffer[pos++] = _quoteChar;
@ -663,7 +661,7 @@ namespace LC.Newtonsoft.Json
/// Writes a <see cref="Byte"/>[] value. /// Writes a <see cref="Byte"/>[] value.
/// </summary> /// </summary>
/// <param name="value">The <see cref="Byte"/>[] value to write.</param> /// <param name="value">The <see cref="Byte"/>[] value to write.</param>
public override void WriteValue(byte[]? value) public override void WriteValue(byte[] value)
{ {
if (value == null) if (value == null)
{ {
@ -688,7 +686,7 @@ namespace LC.Newtonsoft.Json
{ {
InternalWriteValue(JsonToken.Date); InternalWriteValue(JsonToken.Date);
if (StringUtils.IsNullOrEmpty(DateFormatString)) if (string.IsNullOrEmpty(DateFormatString))
{ {
int length = WriteValueToBuffer(value); int length = WriteValueToBuffer(value);
@ -705,7 +703,6 @@ namespace LC.Newtonsoft.Json
private int WriteValueToBuffer(DateTimeOffset value) private int WriteValueToBuffer(DateTimeOffset value)
{ {
EnsureWriteBuffer(); EnsureWriteBuffer();
MiscellaneousUtils.Assert(_writeBuffer != null);
int pos = 0; int pos = 0;
_writeBuffer[pos++] = _quoteChar; _writeBuffer[pos++] = _quoteChar;
@ -723,7 +720,7 @@ namespace LC.Newtonsoft.Json
{ {
InternalWriteValue(JsonToken.String); InternalWriteValue(JsonToken.String);
string text; string text = null;
#if HAVE_CHAR_TO_STRING_WITH_CULTURE #if HAVE_CHAR_TO_STRING_WITH_CULTURE
text = value.ToString("D", CultureInfo.InvariantCulture); text = value.ToString("D", CultureInfo.InvariantCulture);
@ -760,7 +757,7 @@ namespace LC.Newtonsoft.Json
/// Writes a <see cref="Uri"/> value. /// Writes a <see cref="Uri"/> value.
/// </summary> /// </summary>
/// <param name="value">The <see cref="Uri"/> value to write.</param> /// <param name="value">The <see cref="Uri"/> value to write.</param>
public override void WriteValue(Uri? value) public override void WriteValue(Uri value)
{ {
if (value == null) if (value == null)
{ {
@ -778,7 +775,7 @@ namespace LC.Newtonsoft.Json
/// Writes a comment <c>/*...*/</c> containing the specified text. /// Writes a comment <c>/*...*/</c> containing the specified text.
/// </summary> /// </summary>
/// <param name="text">Text to place inside the comment.</param> /// <param name="text">Text to place inside the comment.</param>
public override void WriteComment(string? text) public override void WriteComment(string text)
{ {
InternalWriteComment(); InternalWriteComment();
@ -842,7 +839,6 @@ namespace LC.Newtonsoft.Json
} }
EnsureWriteBuffer(); EnsureWriteBuffer();
MiscellaneousUtils.Assert(_writeBuffer != null);
int totalLength = MathUtils.IntLength(value); int totalLength = MathUtils.IntLength(value);
@ -894,7 +890,6 @@ namespace LC.Newtonsoft.Json
private int WriteNumberToBuffer(uint value, bool negative) private int WriteNumberToBuffer(uint value, bool negative)
{ {
EnsureWriteBuffer(); EnsureWriteBuffer();
MiscellaneousUtils.Assert(_writeBuffer != null);
int totalLength = MathUtils.IntLength(value); int totalLength = MathUtils.IntLength(value);

View File

@ -41,8 +41,6 @@ using System.Linq;
#endif #endif
#nullable disable
namespace LC.Newtonsoft.Json namespace LC.Newtonsoft.Json
{ {
/// <summary> /// <summary>

View File

@ -225,7 +225,7 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
/// classes can override this behaviour for true asynchronicity.</remarks> /// classes can override this behaviour for true asynchronicity.</remarks>
public virtual Task WriteRawAsync(string? json, CancellationToken cancellationToken = default) public virtual Task WriteRawAsync(string json, CancellationToken cancellationToken = default)
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
@ -546,7 +546,7 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
/// classes can override this behaviour for true asynchronicity.</remarks> /// classes can override this behaviour for true asynchronicity.</remarks>
public virtual Task WriteCommentAsync(string? text, CancellationToken cancellationToken = default) public virtual Task WriteCommentAsync(string text, CancellationToken cancellationToken = default)
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
@ -570,7 +570,7 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
/// classes can override this behaviour for true asynchronicity.</remarks> /// classes can override this behaviour for true asynchronicity.</remarks>
public virtual Task WriteRawValueAsync(string? json, CancellationToken cancellationToken = default) public virtual Task WriteRawValueAsync(string json, CancellationToken cancellationToken = default)
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
@ -673,7 +673,7 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
/// classes can override this behaviour for true asynchronicity.</remarks> /// classes can override this behaviour for true asynchronicity.</remarks>
public Task WriteTokenAsync(JsonToken token, object? value, CancellationToken cancellationToken = default) public Task WriteTokenAsync(JsonToken token, object value, CancellationToken cancellationToken = default)
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
@ -755,7 +755,7 @@ namespace LC.Newtonsoft.Json
return WriteValueAsync(guid, cancellationToken); return WriteValueAsync(guid, cancellationToken);
} }
return WriteValueAsync((byte[]?)value, cancellationToken); return WriteValueAsync((byte[])value, cancellationToken);
default: default:
throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(token), token, "Unexpected token type."); throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(token), token, "Unexpected token type.");
} }
@ -768,7 +768,7 @@ namespace LC.Newtonsoft.Json
do do
{ {
// write a JValue date when the constructor is for a date // write a JValue date when the constructor is for a date
if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value.ToString(), "Date", StringComparison.Ordinal))
{ {
await WriteConstructorDateAsync(reader, cancellationToken).ConfigureAwait(false); await WriteConstructorDateAsync(reader, cancellationToken).ConfigureAwait(false);
} }
@ -785,7 +785,7 @@ namespace LC.Newtonsoft.Json
&& writeChildren && writeChildren
&& await reader.ReadAsync(cancellationToken).ConfigureAwait(false)); && await reader.ReadAsync(cancellationToken).ConfigureAwait(false));
if (IsWriteTokenIncomplete(reader, writeChildren, initialDepth)) if (initialDepth < CalculateWriteTokenFinalDepth(reader))
{ {
throw JsonWriterException.Create(this, "Unexpected end when reading token.", null); throw JsonWriterException.Create(this, "Unexpected end when reading token.", null);
} }
@ -801,7 +801,7 @@ namespace LC.Newtonsoft.Json
do do
{ {
// write a JValue date when the constructor is for a date // write a JValue date when the constructor is for a date
if (reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) if (reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value.ToString(), "Date", StringComparison.Ordinal))
{ {
WriteConstructorDate(reader); WriteConstructorDate(reader);
} }
@ -831,7 +831,7 @@ namespace LC.Newtonsoft.Json
throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType, null); throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType, null);
} }
DateTime date = DateTimeUtils.ConvertJavaScriptTicksToDateTime((long)reader.Value!); DateTime date = DateTimeUtils.ConvertJavaScriptTicksToDateTime((long)reader.Value);
if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
{ {
@ -929,7 +929,7 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
/// classes can override this behaviour for true asynchronicity.</remarks> /// classes can override this behaviour for true asynchronicity.</remarks>
public virtual Task WriteValueAsync(byte[]? value, CancellationToken cancellationToken = default) public virtual Task WriteValueAsync(byte[] value, CancellationToken cancellationToken = default)
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
@ -1290,7 +1290,7 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
/// classes can override this behaviour for true asynchronicity.</remarks> /// classes can override this behaviour for true asynchronicity.</remarks>
public virtual Task WriteValueAsync(object? value, CancellationToken cancellationToken = default) public virtual Task WriteValueAsync(object value, CancellationToken cancellationToken = default)
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
@ -1387,7 +1387,7 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
/// classes can override this behaviour for true asynchronicity.</remarks> /// classes can override this behaviour for true asynchronicity.</remarks>
public virtual Task WriteValueAsync(string? value, CancellationToken cancellationToken = default) public virtual Task WriteValueAsync(string value, CancellationToken cancellationToken = default)
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
@ -1524,7 +1524,7 @@ namespace LC.Newtonsoft.Json
/// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous operation.</returns>
/// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived /// <remarks>The default behaviour is to execute synchronously, returning an already-completed task. Derived
/// classes can override this behaviour for true asynchronicity.</remarks> /// classes can override this behaviour for true asynchronicity.</remarks>
public virtual Task WriteValueAsync(Uri? value, CancellationToken cancellationToken = default) public virtual Task WriteValueAsync(Uri value, CancellationToken cancellationToken = default)
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {

View File

@ -62,7 +62,7 @@ namespace LC.Newtonsoft.Json
// array that gives a new state based on the current state an the token being written // array that gives a new state based on the current state an the token being written
private static readonly State[][] StateArray; private static readonly State[][] StateArray;
internal static readonly State[][] StateArrayTemplate = new[] internal static readonly State[][] StateArrayTempate = new[]
{ {
// Start PropertyName ObjectStart Object ArrayStart Array ConstructorStart Constructor Closed Error // Start PropertyName ObjectStart Object ArrayStart Array ConstructorStart Constructor Closed Error
// //
@ -78,9 +78,9 @@ namespace LC.Newtonsoft.Json
internal static State[][] BuildStateArray() internal static State[][] BuildStateArray()
{ {
List<State[]> allStates = StateArrayTemplate.ToList(); List<State[]> allStates = StateArrayTempate.ToList();
State[] errorStates = StateArrayTemplate[0]; State[] errorStates = StateArrayTempate[0];
State[] valueStates = StateArrayTemplate[7]; State[] valueStates = StateArrayTempate[7];
EnumInfo enumValuesAndNames = EnumUtils.GetEnumValuesAndNames(typeof(JsonToken)); EnumInfo enumValuesAndNames = EnumUtils.GetEnumValuesAndNames(typeof(JsonToken));
@ -116,7 +116,7 @@ namespace LC.Newtonsoft.Json
StateArray = BuildStateArray(); StateArray = BuildStateArray();
} }
private List<JsonPosition>? _stack; private List<JsonPosition> _stack;
private JsonPosition _currentPosition; private JsonPosition _currentPosition;
private State _currentState; private State _currentState;
private Formatting _formatting; private Formatting _formatting;
@ -218,7 +218,7 @@ namespace LC.Newtonsoft.Json
JsonPosition? current = insideContainer ? (JsonPosition?)_currentPosition : null; JsonPosition? current = insideContainer ? (JsonPosition?)_currentPosition : null;
return JsonPosition.BuildPath(_stack!, current); return JsonPosition.BuildPath(_stack, current);
} }
} }
@ -226,8 +226,8 @@ namespace LC.Newtonsoft.Json
private DateTimeZoneHandling _dateTimeZoneHandling; private DateTimeZoneHandling _dateTimeZoneHandling;
private StringEscapeHandling _stringEscapeHandling; private StringEscapeHandling _stringEscapeHandling;
private FloatFormatHandling _floatFormatHandling; private FloatFormatHandling _floatFormatHandling;
private string? _dateFormatString; private string _dateFormatString;
private CultureInfo? _culture; private CultureInfo _culture;
/// <summary> /// <summary>
/// Gets or sets a value indicating how JSON text output should be formatted. /// Gets or sets a value indicating how JSON text output should be formatted.
@ -325,7 +325,7 @@ namespace LC.Newtonsoft.Json
/// <summary> /// <summary>
/// Gets or sets how <see cref="DateTime"/> and <see cref="DateTimeOffset"/> values are formatted when writing JSON text. /// Gets or sets how <see cref="DateTime"/> and <see cref="DateTimeOffset"/> values are formatted when writing JSON text.
/// </summary> /// </summary>
public string? DateFormatString public string DateFormatString
{ {
get => _dateFormatString; get => _dateFormatString;
set => _dateFormatString = value; set => _dateFormatString = value;
@ -522,7 +522,7 @@ namespace LC.Newtonsoft.Json
/// A value is only required for tokens that have an associated value, e.g. the <see cref="String"/> property name for <see cref="JsonToken.PropertyName"/>. /// A value is only required for tokens that have an associated value, e.g. the <see cref="String"/> property name for <see cref="JsonToken.PropertyName"/>.
/// <c>null</c> can be passed to the method for tokens that don't have a value, e.g. <see cref="JsonToken.StartObject"/>. /// <c>null</c> can be passed to the method for tokens that don't have a value, e.g. <see cref="JsonToken.StartObject"/>.
/// </param> /// </param>
public void WriteToken(JsonToken token, object? value) public void WriteToken(JsonToken token, object value)
{ {
switch (token) switch (token)
{ {
@ -579,9 +579,8 @@ namespace LC.Newtonsoft.Json
} }
break; break;
case JsonToken.String: case JsonToken.String:
// Allow for a null string. This matches JTokenReader behavior which can read ValidationUtils.ArgumentNotNull(value, nameof(value));
// a JsonToken.String with a null value. WriteValue(value.ToString());
WriteValue(value?.ToString());
break; break;
case JsonToken.Boolean: case JsonToken.Boolean:
ValidationUtils.ArgumentNotNull(value, nameof(value)); ValidationUtils.ArgumentNotNull(value, nameof(value));
@ -626,7 +625,7 @@ namespace LC.Newtonsoft.Json
} }
else else
{ {
WriteValue((byte[])value!); WriteValue((byte[])value);
} }
break; break;
default: default:
@ -650,7 +649,7 @@ namespace LC.Newtonsoft.Json
do do
{ {
// write a JValue date when the constructor is for a date // write a JValue date when the constructor is for a date
if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value.ToString(), "Date", StringComparison.Ordinal))
{ {
WriteConstructorDate(reader); WriteConstructorDate(reader);
} }
@ -667,19 +666,12 @@ namespace LC.Newtonsoft.Json
&& writeChildren && writeChildren
&& reader.Read()); && reader.Read());
if (IsWriteTokenIncomplete(reader, writeChildren, initialDepth)) if (initialDepth < CalculateWriteTokenFinalDepth(reader))
{ {
throw JsonWriterException.Create(this, "Unexpected end when reading token.", null); throw JsonWriterException.Create(this, "Unexpected end when reading token.", null);
} }
} }
private bool IsWriteTokenIncomplete(JsonReader reader, bool writeChildren, int initialDepth)
{
int finalDepth = CalculateWriteTokenFinalDepth(reader);
return initialDepth < finalDepth ||
(writeChildren && initialDepth == finalDepth && JsonTokenUtils.IsStartToken(reader.TokenType));
}
private int CalculateWriteTokenInitialDepth(JsonReader reader) private int CalculateWriteTokenInitialDepth(JsonReader reader)
{ {
JsonToken type = reader.TokenType; JsonToken type = reader.TokenType;
@ -704,7 +696,7 @@ namespace LC.Newtonsoft.Json
private void WriteConstructorDate(JsonReader reader) private void WriteConstructorDate(JsonReader reader)
{ {
if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime dateTime, out string? errorMessage)) if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime dateTime, out string errorMessage))
{ {
throw JsonWriterException.Create(this, errorMessage, null); throw JsonWriterException.Create(this, errorMessage, null);
} }
@ -795,7 +787,7 @@ namespace LC.Newtonsoft.Json
{ {
int currentLevel = top - i; int currentLevel = top - i;
if (_stack![currentLevel].Type == type) if (_stack[currentLevel].Type == type)
{ {
levelsToComplete = i + 2; levelsToComplete = i + 2;
break; break;
@ -917,7 +909,7 @@ namespace LC.Newtonsoft.Json
/// Writes raw JSON without changing the writer's state. /// Writes raw JSON without changing the writer's state.
/// </summary> /// </summary>
/// <param name="json">The raw JSON to write.</param> /// <param name="json">The raw JSON to write.</param>
public virtual void WriteRaw(string? json) public virtual void WriteRaw(string json)
{ {
InternalWriteRaw(); InternalWriteRaw();
} }
@ -926,7 +918,7 @@ namespace LC.Newtonsoft.Json
/// Writes raw JSON where a value is expected and updates the writer's state. /// Writes raw JSON where a value is expected and updates the writer's state.
/// </summary> /// </summary>
/// <param name="json">The raw JSON to write.</param> /// <param name="json">The raw JSON to write.</param>
public virtual void WriteRawValue(string? json) public virtual void WriteRawValue(string json)
{ {
// hack. want writer to change state as if a value had been written // hack. want writer to change state as if a value had been written
UpdateScopeWithFinishedValue(); UpdateScopeWithFinishedValue();
@ -938,7 +930,7 @@ namespace LC.Newtonsoft.Json
/// Writes a <see cref="String"/> value. /// Writes a <see cref="String"/> value.
/// </summary> /// </summary>
/// <param name="value">The <see cref="String"/> value to write.</param> /// <param name="value">The <see cref="String"/> value to write.</param>
public virtual void WriteValue(string? value) public virtual void WriteValue(string value)
{ {
InternalWriteValue(JsonToken.String); InternalWriteValue(JsonToken.String);
} }
@ -1384,7 +1376,7 @@ namespace LC.Newtonsoft.Json
/// Writes a <see cref="Byte"/>[] value. /// Writes a <see cref="Byte"/>[] value.
/// </summary> /// </summary>
/// <param name="value">The <see cref="Byte"/>[] value to write.</param> /// <param name="value">The <see cref="Byte"/>[] value to write.</param>
public virtual void WriteValue(byte[]? value) public virtual void WriteValue(byte[] value)
{ {
if (value == null) if (value == null)
{ {
@ -1400,7 +1392,7 @@ namespace LC.Newtonsoft.Json
/// Writes a <see cref="Uri"/> value. /// Writes a <see cref="Uri"/> value.
/// </summary> /// </summary>
/// <param name="value">The <see cref="Uri"/> value to write.</param> /// <param name="value">The <see cref="Uri"/> value to write.</param>
public virtual void WriteValue(Uri? value) public virtual void WriteValue(Uri value)
{ {
if (value == null) if (value == null)
{ {
@ -1417,7 +1409,7 @@ namespace LC.Newtonsoft.Json
/// An error will raised if the value cannot be written as a single JSON token. /// An error will raised if the value cannot be written as a single JSON token.
/// </summary> /// </summary>
/// <param name="value">The <see cref="Object"/> value to write.</param> /// <param name="value">The <see cref="Object"/> value to write.</param>
public virtual void WriteValue(object? value) public virtual void WriteValue(object value)
{ {
if (value == null) if (value == null)
{ {
@ -1443,7 +1435,7 @@ namespace LC.Newtonsoft.Json
/// Writes a comment <c>/*...*/</c> containing the specified text. /// Writes a comment <c>/*...*/</c> containing the specified text.
/// </summary> /// </summary>
/// <param name="text">Text to place inside the comment.</param> /// <param name="text">Text to place inside the comment.</param>
public virtual void WriteComment(string? text) public virtual void WriteComment(string text)
{ {
InternalWriteComment(); InternalWriteComment();
} }

View File

@ -42,7 +42,7 @@ namespace LC.Newtonsoft.Json
/// Gets the path to the JSON where the error occurred. /// Gets the path to the JSON where the error occurred.
/// </summary> /// </summary>
/// <value>The path to the JSON where the error occurred.</value> /// <value>The path to the JSON where the error occurred.</value>
public string? Path { get; } public string Path { get; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="JsonWriterException"/> class. /// Initializes a new instance of the <see cref="JsonWriterException"/> class.
@ -93,18 +93,18 @@ namespace LC.Newtonsoft.Json
/// <param name="message">The error message that explains the reason for the exception.</param> /// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="path">The path to the JSON where the error occurred.</param> /// <param name="path">The path to the JSON where the error occurred.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or <c>null</c> if no inner exception is specified.</param> /// <param name="innerException">The exception that is the cause of the current exception, or <c>null</c> if no inner exception is specified.</param>
public JsonWriterException(string message, string path, Exception? innerException) public JsonWriterException(string message, string path, Exception innerException)
: base(message, innerException) : base(message, innerException)
{ {
Path = path; Path = path;
} }
internal static JsonWriterException Create(JsonWriter writer, string message, Exception? ex) internal static JsonWriterException Create(JsonWriter writer, string message, Exception ex)
{ {
return Create(writer.ContainerPath, message, ex); return Create(writer.ContainerPath, message, ex);
} }
internal static JsonWriterException Create(string path, string message, Exception? ex) internal static JsonWriterException Create(string path, string message, Exception ex)
{ {
message = JsonPosition.FormatMessage(null, path, message); message = JsonPosition.FormatMessage(null, path, message);

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks Condition="'$(LibraryFrameworks)'==''">netstandard2.0</TargetFrameworks> <TargetFrameworks Condition="'$(LibraryFrameworks)'==''">netstandard2.0</TargetFrameworks>
<TargetFrameworks Condition="'$(LibraryFrameworks)'!=''">$(LibraryFrameworks)</TargetFrameworks> <TargetFrameworks Condition="'$(LibraryFrameworks)'!=''">$(LibraryFrameworks)</TargetFrameworks>
<LangVersion>9.0</LangVersion> <LangVersion>8.0</LangVersion>
<!-- version numbers will be updated by build --> <!-- version numbers will be updated by build -->
<AssemblyVersion>11.0.0.0</AssemblyVersion> <AssemblyVersion>11.0.0.0</AssemblyVersion>
<FileVersion>11.0.1</FileVersion> <FileVersion>11.0.1</FileVersion>
@ -18,34 +18,30 @@
<Title>Json.NET</Title> <Title>Json.NET</Title>
<PackageId>LC.Newtonsoft.Json</PackageId> <PackageId>LC.Newtonsoft.Json</PackageId>
<PackageTags>json</PackageTags> <PackageTags>json</PackageTags>
<PackageIcon>packageIcon.png</PackageIcon> <PackageIconUrl>https://www.newtonsoft.com/content/images/nugeticon.png</PackageIconUrl>
<PackageIconFullPath>$(MSBuildThisFileDirectory)packageIcon.png</PackageIconFullPath>
<PackageProjectUrl>https://www.newtonsoft.com/json</PackageProjectUrl> <PackageProjectUrl>https://www.newtonsoft.com/json</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<PublishRepositoryUrl>true</PublishRepositoryUrl> <PublishRepositoryUrl>true</PublishRepositoryUrl>
<RootNamespace>LC.Newtonsoft.Json</RootNamespace> <RootNamespace>LC.Newtonsoft.Json</RootNamespace>
<AssemblyName>LC.Newtonsoft.Json</AssemblyName> <AssemblyName>LC.Newtonsoft.Json</AssemblyName>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<Nullable>enable</Nullable>
<MinClientVersion>2.12</MinClientVersion> <MinClientVersion>2.12</MinClientVersion>
<IncludeSymbols>true</IncludeSymbols> <IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat> <SymbolPackageFormat>snupkg</SymbolPackageFormat>
<CodeAnalysisRuleset>Newtonsoft.Json.ruleset</CodeAnalysisRuleset> <CodeAnalysisRuleset>Newtonsoft.Json.ruleset</CodeAnalysisRuleset>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<ReleaseVersion>0.7.1</ReleaseVersion> <ReleaseVersion>0.7.1</ReleaseVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Remove="**\*.orig" /> <None Remove="**\*.orig" />
<None Include="..\..\LICENSE.md" Pack="true" PackagePath="LICENSE.md" /> <None Include="..\..\LICENSE.md" Pack="true" PackagePath="LICENSE.md" />
<None Include="$(PackageIconFullPath)" Pack="true" PackagePath="\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="$(MicrosoftCodeAnalysisNetAnalyzersPackageVersion)" PrivateAssets="All" /> <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.2" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="$(MicrosoftSourceLinkGitHubPackageVersion)" PrivateAssets="All" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-18618-05" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="'$(TargetFramework)'=='net45'"> <PropertyGroup Condition="'$(TargetFramework)'=='net45'">
<AssemblyTitle>Json.NET</AssemblyTitle> <AssemblyTitle>Json.NET</AssemblyTitle>
<DefineConstants>HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_FORMATTER;HAVE_BINARY_SERIALIZATION;HAVE_BINARY_EXCEPTION_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FAST_REVERSE;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_EMIT;HAVE_REGEX_TIMEOUTS;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT;HAVE_XML_DOCUMENT_TYPE;HAVE_CONCURRENT_DICTIONARY;$(AdditionalConstants)</DefineConstants> <DefineConstants>HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_FORMATTER;HAVE_BINARY_SERIALIZATION;HAVE_BINARY_EXCEPTION_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FAST_REVERSE;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_EMIT;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT;HAVE_XML_DOCUMENT_TYPE;HAVE_CONCURRENT_DICTIONARY;$(AdditionalConstants)</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)'=='net40'"> <PropertyGroup Condition="'$(TargetFramework)'=='net40'">
<AssemblyTitle>Json.NET .NET 4.0</AssemblyTitle> <AssemblyTitle>Json.NET .NET 4.0</AssemblyTitle>
@ -60,27 +56,42 @@
<DefineConstants>NET20;HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_BINARY_FORMATTER;HAVE_BINARY_SERIALIZATION;HAVE_BINARY_EXCEPTION_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_DB_NULL_TYPE_CODE;HAVE_EMPTY_TYPES;HAVE_FAST_REVERSE;HAVE_FULL_REFLECTION;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_MEMORY_BARRIER;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_REFLECTION_EMIT;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_XML_DOCUMENT;HAVE_XML_DOCUMENT_TYPE;$(AdditionalConstants)</DefineConstants> <DefineConstants>NET20;HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_BINARY_FORMATTER;HAVE_BINARY_SERIALIZATION;HAVE_BINARY_EXCEPTION_SERIALIZATION;HAVE_CAS;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_DB_NULL_TYPE_CODE;HAVE_EMPTY_TYPES;HAVE_FAST_REVERSE;HAVE_FULL_REFLECTION;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_MEMORY_BARRIER;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_REFLECTION_EMIT;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_XML_DOCUMENT;HAVE_XML_DOCUMENT_TYPE;$(AdditionalConstants)</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.0' OR '$(TargetFramework)' == 'netstandard1.3'"> <ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.0' OR '$(TargetFramework)' == 'netstandard1.3'">
<PackageReference Include="Microsoft.CSharp" Version="$(MicrosoftCSharpPackageVersion)" /> <PackageReference Include="Microsoft.CSharp" Version="4.3.0" />
<PackageReference Include="System.ComponentModel.TypeConverter" Version="$(SystemComponentModelTypeConverterPackageVersion)" /> <PackageReference Include="System.ComponentModel.TypeConverter" Version="4.3.0" />
<PackageReference Include="System.Runtime.Serialization.Primitives" Version="$(SystemRuntimeSerializationPrimitivesPackageVersion)" /> <PackageReference Include="System.Runtime.Serialization.Primitives" Version="4.3.0" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.0'"> <PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.0'">
<AssemblyTitle>Json.NET .NET Standard 1.0</AssemblyTitle> <AssemblyTitle>Json.NET .NET Standard 1.0</AssemblyTitle>
<DefineConstants>NETSTANDARD1_0;PORTABLE;HAVE_ASYNC;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DYNAMIC;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_ISET;HAVE_LINQ;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_BINDER;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_OBSOLETE_FORMATTER_ASSEMBLY_STYLE;HAVE_REGEX_TIMEOUTS;$(AdditionalConstants)</DefineConstants> <DefineConstants>NETSTANDARD1_0;PORTABLE;HAVE_ASYNC;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DYNAMIC;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_ISET;HAVE_LINQ;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_BINDER;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_OBSOLETE_FORMATTER_ASSEMBLY_STYLE;$(AdditionalConstants)</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.3'"> <ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.3'">
<PackageReference Include="System.Runtime.Serialization.Formatters" Version="$(SystemRuntimeSerializationFormattersPackageVersion)" /> <PackageReference Include="System.Runtime.Serialization.Formatters" Version="4.3.0" />
<PackageReference Include="System.Xml.XmlDocument" Version="$(SystemXmlXmlDocumentPackageVersion)" /> <PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.3'"> <PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.3'">
<AssemblyTitle>Json.NET .NET Standard 1.3</AssemblyTitle> <AssemblyTitle>Json.NET .NET Standard 1.3</AssemblyTitle>
<DefineConstants>NETSTANDARD1_3;PORTABLE;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_SERIALIZATION;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DYNAMIC;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_BINDER;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_OBSOLETE_FORMATTER_ASSEMBLY_STYLE;HAVE_XML_DOCUMENT;HAVE_CONCURRENT_DICTIONARY;HAVE_ICONVERTIBLE;HAVE_REGEX_TIMEOUTS;HAVE_REGEX_TIMEOUTS;$(AdditionalConstants)</DefineConstants> <DefineConstants>NETSTANDARD1_3;PORTABLE;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_SERIALIZATION;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DYNAMIC;HAVE_EXPRESSIONS;HAVE_FSHARP_TYPES;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_BINDER;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_OBSOLETE_FORMATTER_ASSEMBLY_STYLE;HAVE_XML_DOCUMENT;HAVE_CONCURRENT_DICTIONARY;HAVE_ICONVERTIBLE;$(AdditionalConstants)</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<AssemblyTitle>Json.NET .NET Standard 2.0</AssemblyTitle> <AssemblyTitle>Json.NET .NET Standard 2.0</AssemblyTitle>
<DefineConstants>NETSTANDARD2_0;HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_FORMATTER;HAVE_BINARY_SERIALIZATION;HAVE_BINARY_EXCEPTION_SERIALIZATION;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FAST_REVERSE;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT;HAVE_XML_DOCUMENT_TYPE;HAVE_CONCURRENT_DICTIONARY;HAVE_REGEX_TIMEOUTS;$(AdditionalConstants)</DefineConstants> <DefineConstants>NETSTANDARD2_0;HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_FORMATTER;HAVE_BINARY_SERIALIZATION;HAVE_BINARY_EXCEPTION_SERIALIZATION;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FAST_REVERSE;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT;HAVE_XML_DOCUMENT_TYPE;HAVE_CONCURRENT_DICTIONARY;$(AdditionalConstants)</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition="'$(TargetFramework)' == 'portable-net40+win8+wpa81+wp8+sl5'">
<DefineConstants>HAVE_ADO_NET;HAVE_APP_DOMAIN;HAVE_ASYNC;HAVE_BIG_INTEGER;HAVE_BINARY_FORMATTER;HAVE_BINARY_SERIALIZATION;HAVE_BINARY_EXCEPTION_SERIALIZATION;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_CHAR_TO_STRING_WITH_CULTURE;HAVE_COM_ATTRIBUTES;HAVE_COMPONENT_MODEL;HAVE_CONCURRENT_COLLECTIONS;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_DYNAMIC;HAVE_EMPTY_TYPES;HAVE_ENTITY_FRAMEWORK;HAVE_EXPRESSIONS;HAVE_FAST_REVERSE;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_HASH_SET;HAVE_ICLONEABLE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_INOTIFY_PROPERTY_CHANGING;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_NON_SERIALIZED_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STREAM_READER_WRITER_CLOSE;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_TRACE_WRITER;HAVE_TYPE_DESCRIPTOR;HAVE_UNICODE_SURROGATE_DETECTION;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_XML_DOCUMENT;HAVE_XML_DOCUMENT_TYPE;HAVE_CONCURRENT_DICTIONARY;HAVE_REGEX_TIMEOUTS;;DEBUG;NETSTANDARD;NETSTANDARD2_0;</DefineConstants> <AssemblyTitle>Json.NET Portable .NET 4.0</AssemblyTitle>
<DefineConstants>PORTABLE40;HAVE_CHAR_TO_LOWER_WITH_CULTURE;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DB_NULL_TYPE_CODE;HAVE_FAST_REVERSE;HAVE_FSHARP_TYPES;HAVE_FULL_REFLECTION;HAVE_GUID_TRY_PARSE;HAVE_ICONVERTIBLE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_ISET;HAVE_LINQ;HAVE_MEMORY_BARRIER;HAVE_OBSOLETE_FORMATTER_ASSEMBLY_STYLE;HAVE_SECURITY_SAFE_CRITICAL_ATTRIBUTE;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;$(AdditionalConstants)</DefineConstants>
<TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Profile328</TargetFrameworkProfile>
<NugetTargetMoniker>.NETPortable,Version=v0.0,Profile=Profile328</NugetTargetMoniker>
<LanguageTargets>$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets</LanguageTargets>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'portable-net45+win8+wpa81+wp8'">
<AssemblyTitle>Json.NET Portable</AssemblyTitle>
<DefineConstants>PORTABLE;HAVE_ASYNC;HAVE_COVARIANT_GENERICS;HAVE_DATA_CONTRACTS;HAVE_DATE_TIME_OFFSET;HAVE_DYNAMIC;HAVE_EXPRESSIONS;HAVE_FAST_REVERSE;HAVE_FSHARP_TYPES;HAVE_GUID_TRY_PARSE;HAVE_IGNORE_DATA_MEMBER_ATTRIBUTE;HAVE_ISET;HAVE_LINQ;HAVE_METHOD_IMPL_ATTRIBUTE;HAVE_READ_ONLY_COLLECTIONS;HAVE_REFLECTION_BINDER;HAVE_SERIALIZATION_BINDER_BIND_TO_NAME;HAVE_STRING_JOIN_WITH_ENUMERABLE;HAVE_TIME_SPAN_PARSE_WITH_CULTURE;HAVE_TIME_SPAN_TO_STRING_WITH_CULTURE;HAVE_TIME_ZONE_INFO;HAVE_VARIANT_TYPE_PARAMETERS;HAVE_VERSION_TRY_PARSE;HAVE_XLINQ;HAVE_INOTIFY_COLLECTION_CHANGED;HAVE_OBSOLETE_FORMATTER_ASSEMBLY_STYLE;$(AdditionalConstants)</DefineConstants>
<TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
<NugetTargetMoniker>.NETPortable,Version=v0.0,Profile=Profile259</NugetTargetMoniker>
<LanguageTargets>$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets</LanguageTargets>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@ -27,8 +27,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using System.Globalization; using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
#if !HAVE_LINQ #if !HAVE_LINQ
using LC.Newtonsoft.Json.Utilities.LinqBridge; using LC.Newtonsoft.Json.Utilities.LinqBridge;
#else #else
@ -113,9 +111,9 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param> /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
/// <param name="key">The token key.</param> /// <param name="key">The token key.</param>
/// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the values of every token in the source collection with the given key.</returns> /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the values of every token in the source collection with the given key.</returns>
public static IJEnumerable<JToken> Values(this IEnumerable<JToken> source, object? key) public static IJEnumerable<JToken> Values(this IEnumerable<JToken> source, object key)
{ {
return Values<JToken, JToken>(source, key)!.AsJEnumerable(); return Values<JToken, JToken>(source, key).AsJEnumerable();
} }
/// <summary> /// <summary>
@ -135,7 +133,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param> /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
/// <param name="key">The token key.</param> /// <param name="key">The token key.</param>
/// <returns>An <see cref="IEnumerable{T}"/> that contains the converted values of every token in the source collection with the given key.</returns> /// <returns>An <see cref="IEnumerable{T}"/> that contains the converted values of every token in the source collection with the given key.</returns>
public static IEnumerable<U?> Values<U>(this IEnumerable<JToken> source, object key) public static IEnumerable<U> Values<U>(this IEnumerable<JToken> source, object key)
{ {
return Values<JToken, U>(source, key); return Values<JToken, U>(source, key);
} }
@ -146,7 +144,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <typeparam name="U">The type to convert the values to.</typeparam> /// <typeparam name="U">The type to convert the values to.</typeparam>
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param> /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
/// <returns>An <see cref="IEnumerable{T}"/> that contains the converted values of every token in the source collection.</returns> /// <returns>An <see cref="IEnumerable{T}"/> that contains the converted values of every token in the source collection.</returns>
public static IEnumerable<U?> Values<U>(this IEnumerable<JToken> source) public static IEnumerable<U> Values<U>(this IEnumerable<JToken> source)
{ {
return Values<JToken, U>(source, null); return Values<JToken, U>(source, null);
} }
@ -157,7 +155,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <typeparam name="U">The type to convert the value to.</typeparam> /// <typeparam name="U">The type to convert the value to.</typeparam>
/// <param name="value">A <see cref="JToken"/> cast as a <see cref="IEnumerable{T}"/> of <see cref="JToken"/>.</param> /// <param name="value">A <see cref="JToken"/> cast as a <see cref="IEnumerable{T}"/> of <see cref="JToken"/>.</param>
/// <returns>A converted value.</returns> /// <returns>A converted value.</returns>
public static U? Value<U>(this IEnumerable<JToken> value) public static U Value<U>(this IEnumerable<JToken> value)
{ {
return value.Value<JToken, U>(); return value.Value<JToken, U>();
} }
@ -169,7 +167,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <typeparam name="U">The type to convert the value to.</typeparam> /// <typeparam name="U">The type to convert the value to.</typeparam>
/// <param name="value">A <see cref="JToken"/> cast as a <see cref="IEnumerable{T}"/> of <see cref="JToken"/>.</param> /// <param name="value">A <see cref="JToken"/> cast as a <see cref="IEnumerable{T}"/> of <see cref="JToken"/>.</param>
/// <returns>A converted value.</returns> /// <returns>A converted value.</returns>
public static U? Value<T, U>(this IEnumerable<T> value) where T : JToken public static U Value<T, U>(this IEnumerable<T> value) where T : JToken
{ {
ValidationUtils.ArgumentNotNull(value, nameof(value)); ValidationUtils.ArgumentNotNull(value, nameof(value));
@ -181,7 +179,7 @@ namespace LC.Newtonsoft.Json.Linq
return token.Convert<JToken, U>(); return token.Convert<JToken, U>();
} }
internal static IEnumerable<U?> Values<T, U>(this IEnumerable<T> source, object? key) where T : JToken internal static IEnumerable<U> Values<T, U>(this IEnumerable<T> source, object key) where T : JToken
{ {
ValidationUtils.ArgumentNotNull(source, nameof(source)); ValidationUtils.ArgumentNotNull(source, nameof(source));
@ -206,7 +204,7 @@ namespace LC.Newtonsoft.Json.Linq
{ {
foreach (T token in source) foreach (T token in source)
{ {
JToken? value = token[key]; JToken value = token[key];
if (value != null) if (value != null)
{ {
yield return value.Convert<JToken, U>(); yield return value.Convert<JToken, U>();
@ -226,7 +224,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the values of every token in the source collection.</returns> /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the values of every token in the source collection.</returns>
public static IJEnumerable<JToken> Children<T>(this IEnumerable<T> source) where T : JToken public static IJEnumerable<JToken> Children<T>(this IEnumerable<T> source) where T : JToken
{ {
return Children<T, JToken>(source)!.AsJEnumerable(); return Children<T, JToken>(source).AsJEnumerable();
} }
/// <summary> /// <summary>
@ -236,14 +234,14 @@ namespace LC.Newtonsoft.Json.Linq
/// <typeparam name="U">The type to convert the values to.</typeparam> /// <typeparam name="U">The type to convert the values to.</typeparam>
/// <typeparam name="T">The source collection type.</typeparam> /// <typeparam name="T">The source collection type.</typeparam>
/// <returns>An <see cref="IEnumerable{T}"/> that contains the converted values of every token in the source collection.</returns> /// <returns>An <see cref="IEnumerable{T}"/> that contains the converted values of every token in the source collection.</returns>
public static IEnumerable<U?> Children<T, U>(this IEnumerable<T> source) where T : JToken public static IEnumerable<U> Children<T, U>(this IEnumerable<T> source) where T : JToken
{ {
ValidationUtils.ArgumentNotNull(source, nameof(source)); ValidationUtils.ArgumentNotNull(source, nameof(source));
return source.SelectMany(c => c.Children()).Convert<JToken, U>(); return source.SelectMany(c => c.Children()).Convert<JToken, U>();
} }
internal static IEnumerable<U?> Convert<T, U>(this IEnumerable<T> source) where T : JToken internal static IEnumerable<U> Convert<T, U>(this IEnumerable<T> source) where T : JToken
{ {
ValidationUtils.ArgumentNotNull(source, nameof(source)); ValidationUtils.ArgumentNotNull(source, nameof(source));
@ -253,13 +251,11 @@ namespace LC.Newtonsoft.Json.Linq
} }
} }
internal static U? Convert<T, U>(this T token) where T : JToken? internal static U Convert<T, U>(this T token) where T : JToken
{ {
if (token == null) if (token == null)
{ {
#pragma warning disable CS8653 // A default expression introduces a null value for a type parameter.
return default; return default;
#pragma warning restore CS8653 // A default expression introduces a null value for a type parameter.
} }
if (token is U castValue if (token is U castValue
@ -286,9 +282,7 @@ namespace LC.Newtonsoft.Json.Linq
{ {
if (value.Value == null) if (value.Value == null)
{ {
#pragma warning disable CS8653 // A default expression introduces a null value for a type parameter.
return default; return default;
#pragma warning restore CS8653 // A default expression introduces a null value for a type parameter.
} }
targetType = Nullable.GetUnderlyingType(targetType); targetType = Nullable.GetUnderlyingType(targetType);
@ -321,7 +315,7 @@ namespace LC.Newtonsoft.Json.Linq
{ {
if (source == null) if (source == null)
{ {
return null!; return null;
} }
else if (source is IJEnumerable<T> customEnumerable) else if (source is IJEnumerable<T> customEnumerable)
{ {

View File

@ -73,7 +73,7 @@ namespace LC.Newtonsoft.Json.Linq
/// If this is <c>null</c>, default load settings will be used.</param> /// If this is <c>null</c>, default load settings will be used.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
/// <returns>A <see cref="Task{TResult}"/> representing the asynchronous load. The <see cref="Task{TResult}.Result"/> property contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns> /// <returns>A <see cref="Task{TResult}"/> representing the asynchronous load. The <see cref="Task{TResult}.Result"/> property contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
public new static async Task<JArray> LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) public new static async Task<JArray> LoadAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default)
{ {
if (reader.TokenType == JsonToken.None) if (reader.TokenType == JsonToken.None)
{ {

View File

@ -115,7 +115,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON. /// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
/// If this is <c>null</c>, default load settings will be used.</param> /// If this is <c>null</c>, default load settings will be used.</param>
/// <returns>A <see cref="JArray"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns> /// <returns>A <see cref="JArray"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
public new static JArray Load(JsonReader reader, JsonLoadSettings? settings) public new static JArray Load(JsonReader reader, JsonLoadSettings settings)
{ {
if (reader.TokenType == JsonToken.None) if (reader.TokenType == JsonToken.None)
{ {
@ -163,7 +163,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <example> /// <example>
/// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParseArray" title="Parsing a JSON Array from Text" /> /// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParseArray" title="Parsing a JSON Array from Text" />
/// </example> /// </example>
public new static JArray Parse(string json, JsonLoadSettings? settings) public new static JArray Parse(string json, JsonLoadSettings settings)
{ {
using (JsonReader reader = new JsonTextReader(new StringReader(json))) using (JsonReader reader = new JsonTextReader(new StringReader(json)))
{ {
@ -227,7 +227,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Gets the <see cref="JToken"/> with the specified key. /// Gets the <see cref="JToken"/> with the specified key.
/// </summary> /// </summary>
/// <value>The <see cref="JToken"/> with the specified key.</value> /// <value>The <see cref="JToken"/> with the specified key.</value>
public override JToken? this[object key] public override JToken this[object key]
{ {
get get
{ {
@ -263,19 +263,14 @@ namespace LC.Newtonsoft.Json.Linq
set => SetItem(index, value); set => SetItem(index, value);
} }
internal override int IndexOfItem(JToken? item) internal override int IndexOfItem(JToken item)
{ {
if (item == null)
{
return -1;
}
return _values.IndexOfReference(item); return _values.IndexOfReference(item);
} }
internal override void MergeItem(object content, JsonMergeSettings? settings) internal override void MergeItem(object content, JsonMergeSettings settings)
{ {
IEnumerable? a = (IsMultiContent(content) || content is JArray) IEnumerable a = (IsMultiContent(content) || content is JArray)
? (IEnumerable)content ? (IEnumerable)content
: null; : null;
if (a == null) if (a == null)

View File

@ -43,7 +43,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <returns>A <see cref="Task"/> that represents the asynchronous write operation.</returns> /// <returns>A <see cref="Task"/> that represents the asynchronous write operation.</returns>
public override async Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) public override async Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters)
{ {
await writer.WriteStartConstructorAsync(_name ?? string.Empty, cancellationToken).ConfigureAwait(false); await writer.WriteStartConstructorAsync(_name, cancellationToken).ConfigureAwait(false);
for (int i = 0; i < _values.Count; i++) for (int i = 0; i < _values.Count; i++)
{ {
@ -76,7 +76,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <returns> /// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous load. The <see cref="Task{TResult}.Result"/> /// A <see cref="Task{TResult}"/> that represents the asynchronous load. The <see cref="Task{TResult}.Result"/>
/// property returns a <see cref="JConstructor"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns> /// property returns a <see cref="JConstructor"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
public new static async Task<JConstructor> LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) public new static async Task<JConstructor> LoadAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default)
{ {
if (reader.TokenType == JsonToken.None) if (reader.TokenType == JsonToken.None)
{ {
@ -93,7 +93,7 @@ namespace LC.Newtonsoft.Json.Linq
throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
} }
JConstructor c = new JConstructor((string)reader.Value!); JConstructor c = new JConstructor((string)reader.Value);
c.SetLineInfo(reader as IJsonLineInfo, settings); c.SetLineInfo(reader as IJsonLineInfo, settings);
await c.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(false); await c.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(false);

View File

@ -36,7 +36,7 @@ namespace LC.Newtonsoft.Json.Linq
/// </summary> /// </summary>
public partial class JConstructor : JContainer public partial class JConstructor : JContainer
{ {
private string? _name; private string _name;
private readonly List<JToken> _values = new List<JToken>(); private readonly List<JToken> _values = new List<JToken>();
/// <summary> /// <summary>
@ -45,17 +45,12 @@ namespace LC.Newtonsoft.Json.Linq
/// <value>The container's children tokens.</value> /// <value>The container's children tokens.</value>
protected override IList<JToken> ChildrenTokens => _values; protected override IList<JToken> ChildrenTokens => _values;
internal override int IndexOfItem(JToken? item) internal override int IndexOfItem(JToken item)
{ {
if (item == null)
{
return -1;
}
return _values.IndexOfReference(item); return _values.IndexOfReference(item);
} }
internal override void MergeItem(object content, JsonMergeSettings? settings) internal override void MergeItem(object content, JsonMergeSettings settings)
{ {
if (!(content is JConstructor c)) if (!(content is JConstructor c))
{ {
@ -73,7 +68,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Gets or sets the name of this constructor. /// Gets or sets the name of this constructor.
/// </summary> /// </summary>
/// <value>The constructor name.</value> /// <value>The constructor name.</value>
public string? Name public string Name
{ {
get => _name; get => _name;
set => _name = value; set => _name = value;
@ -159,7 +154,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param> /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
{ {
writer.WriteStartConstructor(_name!); writer.WriteStartConstructor(_name);
int count = _values.Count; int count = _values.Count;
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
@ -174,7 +169,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Gets the <see cref="JToken"/> with the specified key. /// Gets the <see cref="JToken"/> with the specified key.
/// </summary> /// </summary>
/// <value>The <see cref="JToken"/> with the specified key.</value> /// <value>The <see cref="JToken"/> with the specified key.</value>
public override JToken? this[object key] public override JToken this[object key]
{ {
get get
{ {
@ -202,7 +197,7 @@ namespace LC.Newtonsoft.Json.Linq
internal override int GetDeepHashCode() internal override int GetDeepHashCode()
{ {
return (_name?.GetHashCode() ?? 0) ^ ContentsHashCode(); return _name.GetHashCode() ^ ContentsHashCode();
} }
/// <summary> /// <summary>
@ -222,7 +217,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON. /// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
/// If this is <c>null</c>, default load settings will be used.</param> /// If this is <c>null</c>, default load settings will be used.</param>
/// <returns>A <see cref="JConstructor"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns> /// <returns>A <see cref="JConstructor"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
public new static JConstructor Load(JsonReader reader, JsonLoadSettings? settings) public new static JConstructor Load(JsonReader reader, JsonLoadSettings settings)
{ {
if (reader.TokenType == JsonToken.None) if (reader.TokenType == JsonToken.None)
{ {
@ -239,7 +234,7 @@ namespace LC.Newtonsoft.Json.Linq
throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
} }
JConstructor c = new JConstructor((string)reader.Value!); JConstructor c = new JConstructor((string)reader.Value);
c.SetLineInfo(reader as IJsonLineInfo, settings); c.SetLineInfo(reader as IJsonLineInfo, settings);
c.ReadTokenFrom(reader, settings); c.ReadTokenFrom(reader, settings);

View File

@ -26,7 +26,6 @@
#if HAVE_ASYNC #if HAVE_ASYNC
using System; using System;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -36,7 +35,7 @@ namespace LC.Newtonsoft.Json.Linq
{ {
public abstract partial class JContainer public abstract partial class JContainer
{ {
internal async Task ReadTokenFromAsync(JsonReader reader, JsonLoadSettings? options, CancellationToken cancellationToken = default) internal async Task ReadTokenFromAsync(JsonReader reader, JsonLoadSettings options, CancellationToken cancellationToken = default)
{ {
ValidationUtils.ArgumentNotNull(reader, nameof(reader)); ValidationUtils.ArgumentNotNull(reader, nameof(reader));
int startDepth = reader.Depth; int startDepth = reader.Depth;
@ -54,11 +53,11 @@ namespace LC.Newtonsoft.Json.Linq
} }
} }
private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default)
{ {
IJsonLineInfo? lineInfo = reader as IJsonLineInfo; IJsonLineInfo lineInfo = reader as IJsonLineInfo;
JContainer? parent = this; JContainer parent = this;
do do
{ {
@ -72,8 +71,6 @@ namespace LC.Newtonsoft.Json.Linq
parent = parent.Parent; parent = parent.Parent;
} }
MiscellaneousUtils.Assert(parent != null);
switch (reader.TokenType) switch (reader.TokenType)
{ {
case JsonToken.None: case JsonToken.None:
@ -109,7 +106,7 @@ namespace LC.Newtonsoft.Json.Linq
parent = parent.Parent; parent = parent.Parent;
break; break;
case JsonToken.StartConstructor: case JsonToken.StartConstructor:
JConstructor constructor = new JConstructor(reader.Value!.ToString()); JConstructor constructor = new JConstructor(reader.Value.ToString());
constructor.SetLineInfo(lineInfo, settings); constructor.SetLineInfo(lineInfo, settings);
parent.Add(constructor); parent.Add(constructor);
parent = constructor; parent = constructor;
@ -135,7 +132,7 @@ namespace LC.Newtonsoft.Json.Linq
case JsonToken.Comment: case JsonToken.Comment:
if (settings != null && settings.CommentHandling == CommentHandling.Load) if (settings != null && settings.CommentHandling == CommentHandling.Load)
{ {
v = JValue.CreateComment(reader.Value!.ToString()); v = JValue.CreateComment(reader.Value.ToString());
v.SetLineInfo(lineInfo, settings); v.SetLineInfo(lineInfo, settings);
parent.Add(v); parent.Add(v);
} }
@ -151,7 +148,7 @@ namespace LC.Newtonsoft.Json.Linq
parent.Add(v); parent.Add(v);
break; break;
case JsonToken.PropertyName: case JsonToken.PropertyName:
JProperty? property = ReadProperty(reader, settings, lineInfo, parent); JProperty property = ReadProperty(reader, settings, lineInfo, parent);
if (property != null) if (property != null)
{ {
parent = property; parent = property;

View File

@ -33,13 +33,11 @@ using LC.Newtonsoft.Json.Utilities;
using System.Collections; using System.Collections;
using System.Globalization; using System.Globalization;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Diagnostics.CodeAnalysis;
#if !HAVE_LINQ #if !HAVE_LINQ
using LC.Newtonsoft.Json.Utilities.LinqBridge; using LC.Newtonsoft.Json.Utilities.LinqBridge;
#else #else
using System.Linq; using System.Linq;
#endif #endif
namespace LC.Newtonsoft.Json.Linq namespace LC.Newtonsoft.Json.Linq
@ -57,8 +55,8 @@ namespace LC.Newtonsoft.Json.Linq
#endif #endif
{ {
#if HAVE_COMPONENT_MODEL #if HAVE_COMPONENT_MODEL
internal ListChangedEventHandler? _listChanged; internal ListChangedEventHandler _listChanged;
internal AddingNewEventHandler? _addingNew; internal AddingNewEventHandler _addingNew;
/// <summary> /// <summary>
/// Occurs when the list changes or an item in the list changes. /// Occurs when the list changes or an item in the list changes.
@ -79,7 +77,7 @@ namespace LC.Newtonsoft.Json.Linq
} }
#endif #endif
#if HAVE_INOTIFY_COLLECTION_CHANGED #if HAVE_INOTIFY_COLLECTION_CHANGED
internal NotifyCollectionChangedEventHandler? _collectionChanged; internal NotifyCollectionChangedEventHandler _collectionChanged;
/// <summary> /// <summary>
/// Occurs when the items list of the collection has changed, or the collection is reset. /// Occurs when the items list of the collection has changed, or the collection is reset.
@ -97,7 +95,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <value>The container's children tokens.</value> /// <value>The container's children tokens.</value>
protected abstract IList<JToken> ChildrenTokens { get; } protected abstract IList<JToken> ChildrenTokens { get; }
private object? _syncRoot; private object _syncRoot;
#if (HAVE_COMPONENT_MODEL || HAVE_INOTIFY_COLLECTION_CHANGED) #if (HAVE_COMPONENT_MODEL || HAVE_INOTIFY_COLLECTION_CHANGED)
private bool _busy; private bool _busy;
#endif #endif
@ -114,11 +112,9 @@ namespace LC.Newtonsoft.Json.Linq
int i = 0; int i = 0;
foreach (JToken child in other) foreach (JToken child in other)
{ {
TryAddInternal(i, child, false); AddInternal(i, child, false);
i++; i++;
} }
CopyAnnotations(this, other);
} }
internal void CheckReentrancy() internal void CheckReentrancy()
@ -152,7 +148,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="e">The <see cref="ListChangedEventArgs"/> instance containing the event data.</param> /// <param name="e">The <see cref="ListChangedEventArgs"/> instance containing the event data.</param>
protected virtual void OnListChanged(ListChangedEventArgs e) protected virtual void OnListChanged(ListChangedEventArgs e)
{ {
ListChangedEventHandler? handler = _listChanged; ListChangedEventHandler handler = _listChanged;
if (handler != null) if (handler != null)
{ {
@ -175,7 +171,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="e">The <see cref="NotifyCollectionChangedEventArgs"/> instance containing the event data.</param> /// <param name="e">The <see cref="NotifyCollectionChangedEventArgs"/> instance containing the event data.</param>
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{ {
NotifyCollectionChangedEventHandler? handler = _collectionChanged; NotifyCollectionChangedEventHandler handler = _collectionChanged;
if (handler != null) if (handler != null)
{ {
@ -232,7 +228,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <value> /// <value>
/// A <see cref="JToken"/> containing the first child token of the <see cref="JToken"/>. /// A <see cref="JToken"/> containing the first child token of the <see cref="JToken"/>.
/// </value> /// </value>
public override JToken? First public override JToken First
{ {
get get
{ {
@ -247,7 +243,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <value> /// <value>
/// A <see cref="JToken"/> containing the last child token of the <see cref="JToken"/>. /// A <see cref="JToken"/> containing the last child token of the <see cref="JToken"/>.
/// </value> /// </value>
public override JToken? Last public override JToken Last
{ {
get get
{ {
@ -275,7 +271,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <returns> /// <returns>
/// A <see cref="IEnumerable{T}"/> containing the child values of this <see cref="JToken"/>, in document order. /// A <see cref="IEnumerable{T}"/> containing the child values of this <see cref="JToken"/>, in document order.
/// </returns> /// </returns>
public override IEnumerable<T?> Values<T>() where T : default public override IEnumerable<T> Values<T>()
{ {
return ChildrenTokens.Convert<JToken, T>(); return ChildrenTokens.Convert<JToken, T>();
} }
@ -318,12 +314,12 @@ namespace LC.Newtonsoft.Json.Linq
} }
} }
internal bool IsMultiContent([NotNullWhen(true)]object? content) internal bool IsMultiContent(object content)
{ {
return (content is IEnumerable && !(content is string) && !(content is JToken) && !(content is byte[])); return (content is IEnumerable && !(content is string) && !(content is JToken) && !(content is byte[]));
} }
internal JToken EnsureParentToken(JToken? item, bool skipParentCheck) internal JToken EnsureParentToken(JToken item, bool skipParentCheck)
{ {
if (item == null) if (item == null)
{ {
@ -347,9 +343,9 @@ namespace LC.Newtonsoft.Json.Linq
return item; return item;
} }
internal abstract int IndexOfItem(JToken? item); internal abstract int IndexOfItem(JToken item);
internal virtual bool InsertItem(int index, JToken? item, bool skipParentCheck) internal virtual void InsertItem(int index, JToken item, bool skipParentCheck)
{ {
IList<JToken> children = ChildrenTokens; IList<JToken> children = ChildrenTokens;
@ -362,9 +358,9 @@ namespace LC.Newtonsoft.Json.Linq
item = EnsureParentToken(item, skipParentCheck); item = EnsureParentToken(item, skipParentCheck);
JToken? previous = (index == 0) ? null : children[index - 1]; JToken previous = (index == 0) ? null : children[index - 1];
// haven't inserted new token yet so next token is still at the inserting index // haven't inserted new token yet so next token is still at the inserting index
JToken? next = (index == children.Count) ? null : children[index]; JToken next = (index == children.Count) ? null : children[index];
ValidateToken(item, null); ValidateToken(item, null);
@ -396,8 +392,6 @@ namespace LC.Newtonsoft.Json.Linq
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index)); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
} }
#endif #endif
return true;
} }
internal virtual void RemoveItemAt(int index) internal virtual void RemoveItemAt(int index)
@ -416,8 +410,8 @@ namespace LC.Newtonsoft.Json.Linq
CheckReentrancy(); CheckReentrancy();
JToken item = children[index]; JToken item = children[index];
JToken? previous = (index == 0) ? null : children[index - 1]; JToken previous = (index == 0) ? null : children[index - 1];
JToken? next = (index == children.Count - 1) ? null : children[index + 1]; JToken next = (index == children.Count - 1) ? null : children[index + 1];
if (previous != null) if (previous != null)
{ {
@ -448,16 +442,13 @@ namespace LC.Newtonsoft.Json.Linq
#endif #endif
} }
internal virtual bool RemoveItem(JToken? item) internal virtual bool RemoveItem(JToken item)
{ {
if (item != null) int index = IndexOfItem(item);
if (index >= 0)
{ {
int index = IndexOfItem(item); RemoveItemAt(index);
if (index >= 0) return true;
{
RemoveItemAt(index);
return true;
}
} }
return false; return false;
@ -468,7 +459,7 @@ namespace LC.Newtonsoft.Json.Linq
return ChildrenTokens[index]; return ChildrenTokens[index];
} }
internal virtual void SetItem(int index, JToken? item) internal virtual void SetItem(int index, JToken item)
{ {
IList<JToken> children = ChildrenTokens; IList<JToken> children = ChildrenTokens;
@ -494,8 +485,8 @@ namespace LC.Newtonsoft.Json.Linq
ValidateToken(item, existing); ValidateToken(item, existing);
JToken? previous = (index == 0) ? null : children[index - 1]; JToken previous = (index == 0) ? null : children[index - 1];
JToken? next = (index == children.Count - 1) ? null : children[index + 1]; JToken next = (index == children.Count - 1) ? null : children[index + 1];
item.Parent = this; item.Parent = this;
@ -571,7 +562,7 @@ namespace LC.Newtonsoft.Json.Linq
SetItem(index, replacement); SetItem(index, replacement);
} }
internal virtual bool ContainsItem(JToken? item) internal virtual bool ContainsItem(JToken item)
{ {
return (IndexOfItem(item) != -1); return (IndexOfItem(item) != -1);
} }
@ -603,14 +594,14 @@ namespace LC.Newtonsoft.Json.Linq
} }
} }
internal static bool IsTokenUnchanged(JToken currentValue, JToken? newValue) internal static bool IsTokenUnchanged(JToken currentValue, JToken newValue)
{ {
if (currentValue is JValue v1) if (currentValue is JValue v1)
{ {
if (newValue == null) // null will get turned into a JValue of type null
if (v1.Type == JTokenType.Null && newValue == null)
{ {
// null will get turned into a JValue of type null return true;
return v1.Type == JTokenType.Null;
} }
return v1.Equals(newValue); return v1.Equals(newValue);
@ -619,7 +610,7 @@ namespace LC.Newtonsoft.Json.Linq
return false; return false;
} }
internal virtual void ValidateToken(JToken o, JToken? existing) internal virtual void ValidateToken(JToken o, JToken existing)
{ {
ValidationUtils.ArgumentNotNull(o, nameof(o)); ValidationUtils.ArgumentNotNull(o, nameof(o));
@ -633,31 +624,26 @@ namespace LC.Newtonsoft.Json.Linq
/// Adds the specified content as children of this <see cref="JToken"/>. /// Adds the specified content as children of this <see cref="JToken"/>.
/// </summary> /// </summary>
/// <param name="content">The content to be added.</param> /// <param name="content">The content to be added.</param>
public virtual void Add(object? content) public virtual void Add(object content)
{ {
TryAddInternal(ChildrenTokens.Count, content, false); AddInternal(ChildrenTokens.Count, content, false);
}
internal bool TryAdd(object? content)
{
return TryAddInternal(ChildrenTokens.Count, content, false);
} }
internal void AddAndSkipParentCheck(JToken token) internal void AddAndSkipParentCheck(JToken token)
{ {
TryAddInternal(ChildrenTokens.Count, token, true); AddInternal(ChildrenTokens.Count, token, true);
} }
/// <summary> /// <summary>
/// Adds the specified content as the first children of this <see cref="JToken"/>. /// Adds the specified content as the first children of this <see cref="JToken"/>.
/// </summary> /// </summary>
/// <param name="content">The content to be added.</param> /// <param name="content">The content to be added.</param>
public void AddFirst(object? content) public void AddFirst(object content)
{ {
TryAddInternal(0, content, false); AddInternal(0, content, false);
} }
internal bool TryAddInternal(int index, object? content, bool skipParentCheck) internal void AddInternal(int index, object content, bool skipParentCheck)
{ {
if (IsMultiContent(content)) if (IsMultiContent(content))
{ {
@ -666,21 +652,19 @@ namespace LC.Newtonsoft.Json.Linq
int multiIndex = index; int multiIndex = index;
foreach (object c in enumerable) foreach (object c in enumerable)
{ {
TryAddInternal(multiIndex, c, skipParentCheck); AddInternal(multiIndex, c, skipParentCheck);
multiIndex++; multiIndex++;
} }
return true;
} }
else else
{ {
JToken item = CreateFromContent(content); JToken item = CreateFromContent(content);
return InsertItem(index, item, skipParentCheck); InsertItem(index, item, skipParentCheck);
} }
} }
internal static JToken CreateFromContent(object? content) internal static JToken CreateFromContent(object content)
{ {
if (content is JToken token) if (content is JToken token)
{ {
@ -717,7 +701,7 @@ namespace LC.Newtonsoft.Json.Linq
ClearItems(); ClearItems();
} }
internal abstract void MergeItem(object content, JsonMergeSettings? settings); internal abstract void MergeItem(object content, JsonMergeSettings settings);
/// <summary> /// <summary>
/// Merge the specified content into this <see cref="JToken"/>. /// Merge the specified content into this <see cref="JToken"/>.
@ -725,7 +709,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="content">The content to be merged.</param> /// <param name="content">The content to be merged.</param>
public void Merge(object content) public void Merge(object content)
{ {
MergeItem(content, null); MergeItem(content, new JsonMergeSettings());
} }
/// <summary> /// <summary>
@ -733,12 +717,12 @@ namespace LC.Newtonsoft.Json.Linq
/// </summary> /// </summary>
/// <param name="content">The content to be merged.</param> /// <param name="content">The content to be merged.</param>
/// <param name="settings">The <see cref="JsonMergeSettings"/> used to merge the content.</param> /// <param name="settings">The <see cref="JsonMergeSettings"/> used to merge the content.</param>
public void Merge(object content, JsonMergeSettings? settings) public void Merge(object content, JsonMergeSettings settings)
{ {
MergeItem(content, settings); MergeItem(content, settings);
} }
internal void ReadTokenFrom(JsonReader reader, JsonLoadSettings? options) internal void ReadTokenFrom(JsonReader reader, JsonLoadSettings options)
{ {
int startDepth = reader.Depth; int startDepth = reader.Depth;
@ -757,12 +741,12 @@ namespace LC.Newtonsoft.Json.Linq
} }
} }
internal void ReadContentFrom(JsonReader r, JsonLoadSettings? settings) internal void ReadContentFrom(JsonReader r, JsonLoadSettings settings)
{ {
ValidationUtils.ArgumentNotNull(r, nameof(r)); ValidationUtils.ArgumentNotNull(r, nameof(r));
IJsonLineInfo? lineInfo = r as IJsonLineInfo; IJsonLineInfo lineInfo = r as IJsonLineInfo;
JContainer? parent = this; JContainer parent = this;
do do
{ {
@ -776,8 +760,6 @@ namespace LC.Newtonsoft.Json.Linq
parent = parent.Parent; parent = parent.Parent;
} }
MiscellaneousUtils.Assert(parent != null);
switch (r.TokenType) switch (r.TokenType)
{ {
case JsonToken.None: case JsonToken.None:
@ -813,7 +795,7 @@ namespace LC.Newtonsoft.Json.Linq
parent = parent.Parent; parent = parent.Parent;
break; break;
case JsonToken.StartConstructor: case JsonToken.StartConstructor:
JConstructor constructor = new JConstructor(r.Value!.ToString()); JConstructor constructor = new JConstructor(r.Value.ToString());
constructor.SetLineInfo(lineInfo, settings); constructor.SetLineInfo(lineInfo, settings);
parent.Add(constructor); parent.Add(constructor);
parent = constructor; parent = constructor;
@ -839,7 +821,7 @@ namespace LC.Newtonsoft.Json.Linq
case JsonToken.Comment: case JsonToken.Comment:
if (settings != null && settings.CommentHandling == CommentHandling.Load) if (settings != null && settings.CommentHandling == CommentHandling.Load)
{ {
v = JValue.CreateComment(r.Value!.ToString()); v = JValue.CreateComment(r.Value.ToString());
v.SetLineInfo(lineInfo, settings); v.SetLineInfo(lineInfo, settings);
parent.Add(v); parent.Add(v);
} }
@ -855,7 +837,7 @@ namespace LC.Newtonsoft.Json.Linq
parent.Add(v); parent.Add(v);
break; break;
case JsonToken.PropertyName: case JsonToken.PropertyName:
JProperty? property = ReadProperty(r, settings, lineInfo, parent); JProperty property = ReadProperty(r, settings, lineInfo, parent);
if (property != null) if (property != null)
{ {
parent = property; parent = property;
@ -871,13 +853,13 @@ namespace LC.Newtonsoft.Json.Linq
} while (r.Read()); } while (r.Read());
} }
private static JProperty? ReadProperty(JsonReader r, JsonLoadSettings? settings, IJsonLineInfo? lineInfo, JContainer parent) private static JProperty ReadProperty(JsonReader r, JsonLoadSettings settings, IJsonLineInfo lineInfo, JContainer parent)
{ {
DuplicatePropertyNameHandling duplicatePropertyNameHandling = settings?.DuplicatePropertyNameHandling ?? DuplicatePropertyNameHandling.Replace; DuplicatePropertyNameHandling duplicatePropertyNameHandling = settings?.DuplicatePropertyNameHandling ?? DuplicatePropertyNameHandling.Replace;
JObject parentObject = (JObject)parent; JObject parentObject = (JObject)parent;
string propertyName = r.Value!.ToString(); string propertyName = r.Value.ToString();
JProperty? existingPropertyWithName = parentObject.Property(propertyName, StringComparison.Ordinal); JProperty existingPropertyWithName = parentObject.Property(propertyName, StringComparison.Ordinal);
if (existingPropertyWithName != null) if (existingPropertyWithName != null)
{ {
if (duplicatePropertyNameHandling == DuplicatePropertyNameHandling.Ignore) if (duplicatePropertyNameHandling == DuplicatePropertyNameHandling.Ignore)
@ -921,9 +903,9 @@ namespace LC.Newtonsoft.Json.Linq
return string.Empty; return string.Empty;
} }
PropertyDescriptorCollection? ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
{ {
ICustomTypeDescriptor? d = First as ICustomTypeDescriptor; ICustomTypeDescriptor d = First as ICustomTypeDescriptor;
return d?.GetProperties(); return d?.GetProperties();
} }
#endif #endif
@ -980,7 +962,7 @@ namespace LC.Newtonsoft.Json.Linq
} }
#endregion #endregion
private JToken? EnsureValue(object value) private JToken EnsureValue(object value)
{ {
if (value == null) if (value == null)
{ {
@ -1126,7 +1108,7 @@ namespace LC.Newtonsoft.Json.Linq
ListSortDirection IBindingList.SortDirection => ListSortDirection.Ascending; ListSortDirection IBindingList.SortDirection => ListSortDirection.Ascending;
PropertyDescriptor? IBindingList.SortProperty => null; PropertyDescriptor IBindingList.SortProperty => null;
bool IBindingList.SupportsChangeNotification => true; bool IBindingList.SupportsChangeNotification => true;
@ -1136,9 +1118,9 @@ namespace LC.Newtonsoft.Json.Linq
#endif #endif
#endregion #endregion
internal static void MergeEnumerableContent(JContainer target, IEnumerable content, JsonMergeSettings? settings) internal static void MergeEnumerableContent(JContainer target, IEnumerable content, JsonMergeSettings settings)
{ {
switch (settings?.MergeArrayHandling ?? MergeArrayHandling.Concat) switch (settings.MergeArrayHandling)
{ {
case MergeArrayHandling.Concat: case MergeArrayHandling.Concat:
foreach (JToken item in content) foreach (JToken item in content)
@ -1175,10 +1157,6 @@ namespace LC.Newtonsoft.Json.Linq
#endif #endif
break; break;
case MergeArrayHandling.Replace: case MergeArrayHandling.Replace:
if (target == content)
{
break;
}
target.ClearItems(); target.ClearItems();
foreach (JToken item in content) foreach (JToken item in content)
{ {
@ -1191,7 +1169,7 @@ namespace LC.Newtonsoft.Json.Linq
{ {
if (i < target.Count) if (i < target.Count)
{ {
JToken? sourceItem = target[i]; JToken sourceItem = target[i];
if (sourceItem is JContainer existingContainer) if (sourceItem is JContainer existingContainer)
{ {

View File

@ -88,7 +88,7 @@ namespace LC.Newtonsoft.Json.Linq
return JEnumerable<JToken>.Empty; return JEnumerable<JToken>.Empty;
} }
return new JEnumerable<JToken>(_enumerable.Values<T, JToken>(key)!); return new JEnumerable<JToken>(_enumerable.Values<T, JToken>(key));
} }
} }

View File

@ -97,7 +97,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <returns> /// <returns>
/// A <see cref="Task{TResult}"/> that represents the asynchronous load. The <see cref="Task{TResult}.Result"/> /// A <see cref="Task{TResult}"/> that represents the asynchronous load. The <see cref="Task{TResult}.Result"/>
/// property returns a <see cref="JObject"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns> /// property returns a <see cref="JObject"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
public new static async Task<JObject> LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) public new static async Task<JObject> LoadAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default)
{ {
ValidationUtils.ArgumentNotNull(reader, nameof(reader)); ValidationUtils.ArgumentNotNull(reader, nameof(reader));

View File

@ -37,8 +37,6 @@ using System.Linq.Expressions;
using System.IO; using System.IO;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using System.Globalization; using System.Globalization;
using System.Runtime.CompilerServices;
using System.Diagnostics.CodeAnalysis;
#if !HAVE_LINQ #if !HAVE_LINQ
using LC.Newtonsoft.Json.Utilities.LinqBridge; using LC.Newtonsoft.Json.Utilities.LinqBridge;
#else #else
@ -53,7 +51,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <example> /// <example>
/// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParse" title="Parsing a JSON Object from Text" /> /// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParse" title="Parsing a JSON Object from Text" />
/// </example> /// </example>
public partial class JObject : JContainer, IDictionary<string, JToken?>, INotifyPropertyChanged public partial class JObject : JContainer, IDictionary<string, JToken>, INotifyPropertyChanged
#if HAVE_COMPONENT_MODEL #if HAVE_COMPONENT_MODEL
, ICustomTypeDescriptor , ICustomTypeDescriptor
#endif #endif
@ -72,13 +70,13 @@ namespace LC.Newtonsoft.Json.Linq
/// <summary> /// <summary>
/// Occurs when a property value changes. /// Occurs when a property value changes.
/// </summary> /// </summary>
public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
#if HAVE_INOTIFY_PROPERTY_CHANGING #if HAVE_INOTIFY_PROPERTY_CHANGING
/// <summary> /// <summary>
/// Occurs when a property value is changing. /// Occurs when a property value is changing.
/// </summary> /// </summary>
public event PropertyChangingEventHandler? PropertyChanging; public event PropertyChangingEventHandler PropertyChanging;
#endif #endif
/// <summary> /// <summary>
@ -125,28 +123,23 @@ namespace LC.Newtonsoft.Json.Linq
return _properties.Compare(t._properties); return _properties.Compare(t._properties);
} }
internal override int IndexOfItem(JToken? item) internal override int IndexOfItem(JToken item)
{ {
if (item == null)
{
return -1;
}
return _properties.IndexOfReference(item); return _properties.IndexOfReference(item);
} }
internal override bool InsertItem(int index, JToken? item, bool skipParentCheck) internal override void InsertItem(int index, JToken item, bool skipParentCheck)
{ {
// don't add comments to JObject, no name to reference comment by // don't add comments to JObject, no name to reference comment by
if (item != null && item.Type == JTokenType.Comment) if (item != null && item.Type == JTokenType.Comment)
{ {
return false; return;
} }
return base.InsertItem(index, item, skipParentCheck); base.InsertItem(index, item, skipParentCheck);
} }
internal override void ValidateToken(JToken o, JToken? existing) internal override void ValidateToken(JToken o, JToken existing)
{ {
ValidationUtils.ArgumentNotNull(o, nameof(o)); ValidationUtils.ArgumentNotNull(o, nameof(o));
@ -173,16 +166,16 @@ namespace LC.Newtonsoft.Json.Linq
} }
} }
internal override void MergeItem(object content, JsonMergeSettings? settings) internal override void MergeItem(object content, JsonMergeSettings settings)
{ {
if (!(content is JObject o)) if (!(content is JObject o))
{ {
return; return;
} }
foreach (KeyValuePair<string, JToken?> contentItem in o) foreach (KeyValuePair<string, JToken> contentItem in o)
{ {
JProperty? existingProperty = Property(contentItem.Key, settings?.PropertyNameComparison ?? StringComparison.Ordinal); JProperty existingProperty = Property(contentItem.Key, settings?.PropertyNameComparison ?? StringComparison.Ordinal);
if (existingProperty == null) if (existingProperty == null)
{ {
@ -269,7 +262,7 @@ namespace LC.Newtonsoft.Json.Linq
/// </summary> /// </summary>
/// <param name="name">The property name.</param> /// <param name="name">The property name.</param>
/// <returns>A <see cref="JProperty"/> with the specified name or <c>null</c>.</returns> /// <returns>A <see cref="JProperty"/> with the specified name or <c>null</c>.</returns>
public JProperty? Property(string name) public JProperty Property(string name)
{ {
return Property(name, StringComparison.Ordinal); return Property(name, StringComparison.Ordinal);
} }
@ -282,14 +275,14 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="name">The property name.</param> /// <param name="name">The property name.</param>
/// <param name="comparison">One of the enumeration values that specifies how the strings will be compared.</param> /// <param name="comparison">One of the enumeration values that specifies how the strings will be compared.</param>
/// <returns>A <see cref="JProperty"/> matched with the specified name or <c>null</c>.</returns> /// <returns>A <see cref="JProperty"/> matched with the specified name or <c>null</c>.</returns>
public JProperty? Property(string name, StringComparison comparison) public JProperty Property(string name, StringComparison comparison)
{ {
if (name == null) if (name == null)
{ {
return null; return null;
} }
if (_properties.TryGetValue(name, out JToken? property)) if (_properties.TryGetValue(name, out JToken property))
{ {
return (JProperty)property; return (JProperty)property;
} }
@ -323,7 +316,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Gets the <see cref="JToken"/> with the specified key. /// Gets the <see cref="JToken"/> with the specified key.
/// </summary> /// </summary>
/// <value>The <see cref="JToken"/> with the specified key.</value> /// <value>The <see cref="JToken"/> with the specified key.</value>
public override JToken? this[object key] public override JToken this[object key]
{ {
get get
{ {
@ -353,29 +346,29 @@ namespace LC.Newtonsoft.Json.Linq
/// Gets or sets the <see cref="JToken"/> with the specified property name. /// Gets or sets the <see cref="JToken"/> with the specified property name.
/// </summary> /// </summary>
/// <value></value> /// <value></value>
public JToken? this[string propertyName] public JToken this[string propertyName]
{ {
get get
{ {
ValidationUtils.ArgumentNotNull(propertyName, nameof(propertyName)); ValidationUtils.ArgumentNotNull(propertyName, nameof(propertyName));
JProperty? property = Property(propertyName, StringComparison.Ordinal); JProperty property = Property(propertyName, StringComparison.Ordinal);
return property?.Value; return property?.Value;
} }
set set
{ {
JProperty? property = Property(propertyName, StringComparison.Ordinal); JProperty property = Property(propertyName, StringComparison.Ordinal);
if (property != null) if (property != null)
{ {
property.Value = value!; property.Value = value;
} }
else else
{ {
#if HAVE_INOTIFY_PROPERTY_CHANGING #if HAVE_INOTIFY_PROPERTY_CHANGING
OnPropertyChanging(propertyName); OnPropertyChanging(propertyName);
#endif #endif
Add(propertyName, value); Add(new JProperty(propertyName, value));
OnPropertyChanged(propertyName); OnPropertyChanged(propertyName);
} }
} }
@ -404,7 +397,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <exception cref="JsonReaderException"> /// <exception cref="JsonReaderException">
/// <paramref name="reader"/> is not valid JSON. /// <paramref name="reader"/> is not valid JSON.
/// </exception> /// </exception>
public new static JObject Load(JsonReader reader, JsonLoadSettings? settings) public new static JObject Load(JsonReader reader, JsonLoadSettings settings)
{ {
ValidationUtils.ArgumentNotNull(reader, nameof(reader)); ValidationUtils.ArgumentNotNull(reader, nameof(reader));
@ -460,7 +453,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <example> /// <example>
/// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParse" title="Parsing a JSON Object from Text" /> /// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParse" title="Parsing a JSON Object from Text" />
/// </example> /// </example>
public new static JObject Parse(string json, JsonLoadSettings? settings) public new static JObject Parse(string json, JsonLoadSettings settings)
{ {
using (JsonReader reader = new JsonTextReader(new StringReader(json))) using (JsonReader reader = new JsonTextReader(new StringReader(json)))
{ {
@ -495,7 +488,7 @@ namespace LC.Newtonsoft.Json.Linq
{ {
JToken token = FromObjectInternal(o, jsonSerializer); JToken token = FromObjectInternal(o, jsonSerializer);
if (token.Type != JTokenType.Object) if (token != null && token.Type != JTokenType.Object)
{ {
throw new ArgumentException("Object serialized to {0}. JObject instance expected.".FormatWith(CultureInfo.InvariantCulture, token.Type)); throw new ArgumentException("Object serialized to {0}. JObject instance expected.".FormatWith(CultureInfo.InvariantCulture, token.Type));
} }
@ -525,7 +518,7 @@ namespace LC.Newtonsoft.Json.Linq
/// </summary> /// </summary>
/// <param name="propertyName">Name of the property.</param> /// <param name="propertyName">Name of the property.</param>
/// <returns>The <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.</returns> /// <returns>The <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.</returns>
public JToken? GetValue(string? propertyName) public JToken GetValue(string propertyName)
{ {
return GetValue(propertyName, StringComparison.Ordinal); return GetValue(propertyName, StringComparison.Ordinal);
} }
@ -538,7 +531,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="propertyName">Name of the property.</param> /// <param name="propertyName">Name of the property.</param>
/// <param name="comparison">One of the enumeration values that specifies how the strings will be compared.</param> /// <param name="comparison">One of the enumeration values that specifies how the strings will be compared.</param>
/// <returns>The <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.</returns> /// <returns>The <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.</returns>
public JToken? GetValue(string? propertyName, StringComparison comparison) public JToken GetValue(string propertyName, StringComparison comparison)
{ {
if (propertyName == null) if (propertyName == null)
{ {
@ -560,7 +553,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <param name="comparison">One of the enumeration values that specifies how the strings will be compared.</param> /// <param name="comparison">One of the enumeration values that specifies how the strings will be compared.</param>
/// <returns><c>true</c> if a value was successfully retrieved; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if a value was successfully retrieved; otherwise, <c>false</c>.</returns>
public bool TryGetValue(string propertyName, StringComparison comparison, [NotNullWhen(true)]out JToken? value) public bool TryGetValue(string propertyName, StringComparison comparison, out JToken value)
{ {
value = GetValue(propertyName, comparison); value = GetValue(propertyName, comparison);
return (value != null); return (value != null);
@ -572,7 +565,7 @@ namespace LC.Newtonsoft.Json.Linq
/// </summary> /// </summary>
/// <param name="propertyName">Name of the property.</param> /// <param name="propertyName">Name of the property.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
public void Add(string propertyName, JToken? value) public void Add(string propertyName, JToken value)
{ {
Add(new JProperty(propertyName, value)); Add(new JProperty(propertyName, value));
} }
@ -589,7 +582,7 @@ namespace LC.Newtonsoft.Json.Linq
return _properties.Contains(propertyName); return _properties.Contains(propertyName);
} }
ICollection<string> IDictionary<string, JToken?>.Keys => _properties.Keys; ICollection<string> IDictionary<string, JToken>.Keys => _properties.Keys;
/// <summary> /// <summary>
/// Removes the property with the specified name. /// Removes the property with the specified name.
@ -598,7 +591,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <returns><c>true</c> if item was successfully removed; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if item was successfully removed; otherwise, <c>false</c>.</returns>
public bool Remove(string propertyName) public bool Remove(string propertyName)
{ {
JProperty? property = Property(propertyName, StringComparison.Ordinal); JProperty property = Property(propertyName, StringComparison.Ordinal);
if (property == null) if (property == null)
{ {
return false; return false;
@ -614,9 +607,9 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="propertyName">Name of the property.</param> /// <param name="propertyName">Name of the property.</param>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <returns><c>true</c> if a value was successfully retrieved; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if a value was successfully retrieved; otherwise, <c>false</c>.</returns>
public bool TryGetValue(string propertyName, [NotNullWhen(true)]out JToken? value) public bool TryGetValue(string propertyName, out JToken value)
{ {
JProperty? property = Property(propertyName, StringComparison.Ordinal); JProperty property = Property(propertyName, StringComparison.Ordinal);
if (property == null) if (property == null)
{ {
value = null; value = null;
@ -627,24 +620,24 @@ namespace LC.Newtonsoft.Json.Linq
return true; return true;
} }
ICollection<JToken?> IDictionary<string, JToken?>.Values => throw new NotImplementedException(); ICollection<JToken> IDictionary<string, JToken>.Values => throw new NotImplementedException();
#endregion #endregion
#region ICollection<KeyValuePair<string,JToken>> Members #region ICollection<KeyValuePair<string,JToken>> Members
void ICollection<KeyValuePair<string, JToken?>>.Add(KeyValuePair<string, JToken?> item) void ICollection<KeyValuePair<string, JToken>>.Add(KeyValuePair<string, JToken> item)
{ {
Add(new JProperty(item.Key, item.Value)); Add(new JProperty(item.Key, item.Value));
} }
void ICollection<KeyValuePair<string, JToken?>>.Clear() void ICollection<KeyValuePair<string, JToken>>.Clear()
{ {
RemoveAll(); RemoveAll();
} }
bool ICollection<KeyValuePair<string, JToken?>>.Contains(KeyValuePair<string, JToken?> item) bool ICollection<KeyValuePair<string, JToken>>.Contains(KeyValuePair<string, JToken> item)
{ {
JProperty? property = Property(item.Key, StringComparison.Ordinal); JProperty property = Property(item.Key, StringComparison.Ordinal);
if (property == null) if (property == null)
{ {
return false; return false;
@ -653,7 +646,7 @@ namespace LC.Newtonsoft.Json.Linq
return (property.Value == item.Value); return (property.Value == item.Value);
} }
void ICollection<KeyValuePair<string, JToken?>>.CopyTo(KeyValuePair<string, JToken?>[] array, int arrayIndex) void ICollection<KeyValuePair<string, JToken>>.CopyTo(KeyValuePair<string, JToken>[] array, int arrayIndex)
{ {
if (array == null) if (array == null)
{ {
@ -675,16 +668,16 @@ namespace LC.Newtonsoft.Json.Linq
int index = 0; int index = 0;
foreach (JProperty property in _properties) foreach (JProperty property in _properties)
{ {
array[arrayIndex + index] = new KeyValuePair<string, JToken?>(property.Name, property.Value); array[arrayIndex + index] = new KeyValuePair<string, JToken>(property.Name, property.Value);
index++; index++;
} }
} }
bool ICollection<KeyValuePair<string, JToken?>>.IsReadOnly => false; bool ICollection<KeyValuePair<string, JToken>>.IsReadOnly => false;
bool ICollection<KeyValuePair<string, JToken?>>.Remove(KeyValuePair<string, JToken?> item) bool ICollection<KeyValuePair<string, JToken>>.Remove(KeyValuePair<string, JToken> item)
{ {
if (!((ICollection<KeyValuePair<string, JToken?>>)this).Contains(item)) if (!((ICollection<KeyValuePair<string, JToken>>)this).Contains(item))
{ {
return false; return false;
} }
@ -705,11 +698,11 @@ namespace LC.Newtonsoft.Json.Linq
/// <returns> /// <returns>
/// A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection. /// A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection.
/// </returns> /// </returns>
public IEnumerator<KeyValuePair<string, JToken?>> GetEnumerator() public IEnumerator<KeyValuePair<string, JToken>> GetEnumerator()
{ {
foreach (JProperty property in _properties) foreach (JProperty property in _properties)
{ {
yield return new KeyValuePair<string, JToken?>(property.Name, property.Value); yield return new KeyValuePair<string, JToken>(property.Name, property.Value);
} }
} }
@ -744,15 +737,14 @@ namespace LC.Newtonsoft.Json.Linq
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{ {
PropertyDescriptor[] propertiesArray = new PropertyDescriptor[Count]; PropertyDescriptorCollection descriptors = new PropertyDescriptorCollection(null);
int i = 0;
foreach (KeyValuePair<string, JToken?> propertyValue in this) foreach (KeyValuePair<string, JToken> propertyValue in this)
{ {
propertiesArray[i] = new JPropertyDescriptor(propertyValue.Key); descriptors.Add(new JPropertyDescriptor(propertyValue.Key));
i++;
} }
return new PropertyDescriptorCollection(propertiesArray); return descriptors;
} }
AttributeCollection ICustomTypeDescriptor.GetAttributes() AttributeCollection ICustomTypeDescriptor.GetAttributes()
@ -760,12 +752,12 @@ namespace LC.Newtonsoft.Json.Linq
return AttributeCollection.Empty; return AttributeCollection.Empty;
} }
string? ICustomTypeDescriptor.GetClassName() string ICustomTypeDescriptor.GetClassName()
{ {
return null; return null;
} }
string? ICustomTypeDescriptor.GetComponentName() string ICustomTypeDescriptor.GetComponentName()
{ {
return null; return null;
} }
@ -775,17 +767,17 @@ namespace LC.Newtonsoft.Json.Linq
return new TypeConverter(); return new TypeConverter();
} }
EventDescriptor? ICustomTypeDescriptor.GetDefaultEvent() EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
{ {
return null; return null;
} }
PropertyDescriptor? ICustomTypeDescriptor.GetDefaultProperty() PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
{ {
return null; return null;
} }
object? ICustomTypeDescriptor.GetEditor(Type editorBaseType) object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
{ {
return null; return null;
} }
@ -800,7 +792,7 @@ namespace LC.Newtonsoft.Json.Linq
return EventDescriptorCollection.Empty; return EventDescriptorCollection.Empty;
} }
object? ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
{ {
if (pd is JPropertyDescriptor) if (pd is JPropertyDescriptor)
{ {
@ -828,7 +820,7 @@ namespace LC.Newtonsoft.Json.Linq
private class JObjectDynamicProxy : DynamicProxy<JObject> private class JObjectDynamicProxy : DynamicProxy<JObject>
{ {
public override bool TryGetMember(JObject instance, GetMemberBinder binder, out object? result) public override bool TryGetMember(JObject instance, GetMemberBinder binder, out object result)
{ {
// result can be null // result can be null
result = instance[binder.Name]; result = instance[binder.Name];

View File

@ -88,7 +88,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param> /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="CancellationToken.None"/>.</param>
/// <returns>A <see cref="Task{TResult}"/> representing the asynchronous creation. The <see cref="Task{TResult}.Result"/> /// <returns>A <see cref="Task{TResult}"/> representing the asynchronous creation. The <see cref="Task{TResult}.Result"/>
/// property returns a <see cref="JProperty"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns> /// property returns a <see cref="JProperty"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
public new static async Task<JProperty> LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) public new static async Task<JProperty> LoadAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default)
{ {
if (reader.TokenType == JsonToken.None) if (reader.TokenType == JsonToken.None)
{ {
@ -105,7 +105,7 @@ namespace LC.Newtonsoft.Json.Linq
throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
} }
JProperty p = new JProperty((string)reader.Value!); JProperty p = new JProperty((string)reader.Value);
p.SetLineInfo(reader as IJsonLineInfo, settings); p.SetLineInfo(reader as IJsonLineInfo, settings);
await p.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(false); await p.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(false);

View File

@ -40,7 +40,7 @@ namespace LC.Newtonsoft.Json.Linq
#region JPropertyList #region JPropertyList
private class JPropertyList : IList<JToken> private class JPropertyList : IList<JToken>
{ {
internal JToken? _token; internal JToken _token;
public IEnumerator<JToken> GetEnumerator() public IEnumerator<JToken> GetEnumerator()
{ {
@ -115,24 +115,13 @@ namespace LC.Newtonsoft.Json.Linq
public JToken this[int index] public JToken this[int index]
{ {
get get => (index == 0) ? _token : null;
{
if (index != 0)
{
throw new IndexOutOfRangeException();
}
MiscellaneousUtils.Assert(_token != null);
return _token;
}
set set
{ {
if (index != 0) if (index == 0)
{ {
throw new IndexOutOfRangeException(); _token = value;
} }
_token = value;
} }
} }
} }
@ -164,7 +153,7 @@ namespace LC.Newtonsoft.Json.Linq
public JToken Value public JToken Value
{ {
[DebuggerStepThrough] [DebuggerStepThrough]
get { return _content._token!; } get { return _content._token; }
set set
{ {
CheckReentrancy(); CheckReentrancy();
@ -202,7 +191,7 @@ namespace LC.Newtonsoft.Json.Linq
return Value; return Value;
} }
internal override void SetItem(int index, JToken? item) internal override void SetItem(int index, JToken item)
{ {
if (index != 0) if (index != 0)
{ {
@ -214,14 +203,14 @@ namespace LC.Newtonsoft.Json.Linq
return; return;
} }
((JObject?)Parent)?.InternalPropertyChanging(this); ((JObject)Parent)?.InternalPropertyChanging(this);
base.SetItem(0, item); base.SetItem(0, item);
((JObject?)Parent)?.InternalPropertyChanged(this); ((JObject)Parent)?.InternalPropertyChanged(this);
} }
internal override bool RemoveItem(JToken? item) internal override bool RemoveItem(JToken item)
{ {
throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
} }
@ -231,22 +220,17 @@ namespace LC.Newtonsoft.Json.Linq
throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
} }
internal override int IndexOfItem(JToken? item) internal override int IndexOfItem(JToken item)
{ {
if (item == null)
{
return -1;
}
return _content.IndexOf(item); return _content.IndexOf(item);
} }
internal override bool InsertItem(int index, JToken? item, bool skipParentCheck) internal override void InsertItem(int index, JToken item, bool skipParentCheck)
{ {
// don't add comments to JProperty // don't add comments to JProperty
if (item != null && item.Type == JTokenType.Comment) if (item != null && item.Type == JTokenType.Comment)
{ {
return false; return;
} }
if (Value != null) if (Value != null)
@ -254,17 +238,17 @@ namespace LC.Newtonsoft.Json.Linq
throw new JsonException("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); throw new JsonException("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
} }
return base.InsertItem(0, item, false); base.InsertItem(0, item, false);
} }
internal override bool ContainsItem(JToken? item) internal override bool ContainsItem(JToken item)
{ {
return (Value == item); return (Value == item);
} }
internal override void MergeItem(object content, JsonMergeSettings? settings) internal override void MergeItem(object content, JsonMergeSettings settings)
{ {
JToken? value = (content as JProperty)?.Value; JToken value = (content as JProperty)?.Value;
if (value != null && value.Type != JTokenType.Null) if (value != null && value.Type != JTokenType.Null)
{ {
@ -320,7 +304,7 @@ namespace LC.Newtonsoft.Json.Linq
/// </summary> /// </summary>
/// <param name="name">The property name.</param> /// <param name="name">The property name.</param>
/// <param name="content">The property content.</param> /// <param name="content">The property content.</param>
public JProperty(string name, object? content) public JProperty(string name, object content)
{ {
ValidationUtils.ArgumentNotNull(name, nameof(name)); ValidationUtils.ArgumentNotNull(name, nameof(name));
@ -373,7 +357,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON. /// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
/// If this is <c>null</c>, default load settings will be used.</param> /// If this is <c>null</c>, default load settings will be used.</param>
/// <returns>A <see cref="JProperty"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns> /// <returns>A <see cref="JProperty"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
public new static JProperty Load(JsonReader reader, JsonLoadSettings? settings) public new static JProperty Load(JsonReader reader, JsonLoadSettings settings)
{ {
if (reader.TokenType == JsonToken.None) if (reader.TokenType == JsonToken.None)
{ {
@ -390,7 +374,7 @@ namespace LC.Newtonsoft.Json.Linq
throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
} }
JProperty p = new JProperty((string)reader.Value!); JProperty p = new JProperty((string)reader.Value);
p.SetLineInfo(reader as IJsonLineInfo, settings); p.SetLineInfo(reader as IJsonLineInfo, settings);
p.ReadTokenFrom(reader, settings); p.ReadTokenFrom(reader, settings);

View File

@ -67,7 +67,7 @@ namespace LC.Newtonsoft.Json.Linq
/// The value of a property for a given component. /// The value of a property for a given component.
/// </returns> /// </returns>
/// <param name="component">The component with the property for which to retrieve the value.</param> /// <param name="component">The component with the property for which to retrieve the value.</param>
public override object? GetValue(object component) public override object GetValue(object component)
{ {
return (component as JObject)?[Name]; return (component as JObject)?[Name];
} }

View File

@ -26,8 +26,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
namespace LC.Newtonsoft.Json.Linq namespace LC.Newtonsoft.Json.Linq
@ -36,7 +34,7 @@ namespace LC.Newtonsoft.Json.Linq
{ {
private static readonly IEqualityComparer<string> Comparer = StringComparer.Ordinal; private static readonly IEqualityComparer<string> Comparer = StringComparer.Ordinal;
private Dictionary<string, JToken>? _dictionary; private Dictionary<string, JToken> _dictionary;
public JPropertyKeyedCollection() : base(new List<JToken>()) public JPropertyKeyedCollection() : base(new List<JToken>())
{ {
@ -45,7 +43,7 @@ namespace LC.Newtonsoft.Json.Linq
private void AddKey(string key, JToken item) private void AddKey(string key, JToken item)
{ {
EnsureDictionary(); EnsureDictionary();
_dictionary![key] = item; _dictionary[key] = item;
} }
protected void ChangeItemKey(JToken item, string newKey) protected void ChangeItemKey(JToken item, string newKey)
@ -191,7 +189,7 @@ namespace LC.Newtonsoft.Json.Linq
} }
} }
public bool TryGetValue(string key, [NotNullWhen(true)]out JToken? value) public bool TryGetValue(string key, out JToken value)
{ {
if (_dictionary == null) if (_dictionary == null)
{ {
@ -207,7 +205,7 @@ namespace LC.Newtonsoft.Json.Linq
get get
{ {
EnsureDictionary(); EnsureDictionary();
return _dictionary!.Keys; return _dictionary.Keys;
} }
} }
@ -216,7 +214,7 @@ namespace LC.Newtonsoft.Json.Linq
get get
{ {
EnsureDictionary(); EnsureDictionary();
return _dictionary!.Values; return _dictionary.Values;
} }
} }
@ -234,8 +232,8 @@ namespace LC.Newtonsoft.Json.Linq
// dictionaries in JavaScript aren't ordered // dictionaries in JavaScript aren't ordered
// ignore order when comparing properties // ignore order when comparing properties
Dictionary<string, JToken>? d1 = _dictionary; Dictionary<string, JToken> d1 = _dictionary;
Dictionary<string, JToken>? d2 = other._dictionary; Dictionary<string, JToken> d2 = other._dictionary;
if (d1 == null && d2 == null) if (d1 == null && d2 == null)
{ {
@ -244,7 +242,7 @@ namespace LC.Newtonsoft.Json.Linq
if (d1 == null) if (d1 == null)
{ {
return (d2!.Count == 0); return (d2.Count == 0);
} }
if (d2 == null) if (d2 == null)

View File

@ -46,7 +46,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Initializes a new instance of the <see cref="JRaw"/> class. /// Initializes a new instance of the <see cref="JRaw"/> class.
/// </summary> /// </summary>
/// <param name="rawJson">The raw json.</param> /// <param name="rawJson">The raw json.</param>
public JRaw(object? rawJson) public JRaw(object rawJson)
: base(rawJson, JTokenType.Raw) : base(rawJson, JTokenType.Raw)
{ {
} }

View File

@ -89,7 +89,7 @@ namespace LC.Newtonsoft.Json.Linq
/// that were read from the reader. The runtime type of the token is determined /// that were read from the reader. The runtime type of the token is determined
/// by the token type of the first token encountered in the reader. /// by the token type of the first token encountered in the reader.
/// </returns> /// </returns>
public static async Task<JToken> ReadFromAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) public static async Task<JToken> ReadFromAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default)
{ {
ValidationUtils.ArgumentNotNull(reader, nameof(reader)); ValidationUtils.ArgumentNotNull(reader, nameof(reader));
@ -101,7 +101,7 @@ namespace LC.Newtonsoft.Json.Linq
} }
} }
IJsonLineInfo? lineInfo = reader as IJsonLineInfo; IJsonLineInfo lineInfo = reader as IJsonLineInfo;
switch (reader.TokenType) switch (reader.TokenType)
{ {
@ -123,7 +123,7 @@ namespace LC.Newtonsoft.Json.Linq
v.SetLineInfo(lineInfo, settings); v.SetLineInfo(lineInfo, settings);
return v; return v;
case JsonToken.Comment: case JsonToken.Comment:
v = JValue.CreateComment(reader.Value?.ToString()); v = JValue.CreateComment(reader.Value.ToString());
v.SetLineInfo(lineInfo, settings); v.SetLineInfo(lineInfo, settings);
return v; return v;
case JsonToken.Null: case JsonToken.Null:
@ -168,7 +168,7 @@ namespace LC.Newtonsoft.Json.Linq
/// that were read from the reader. The runtime type of the token is determined /// that were read from the reader. The runtime type of the token is determined
/// by the token type of the first token encountered in the reader. /// by the token type of the first token encountered in the reader.
/// </returns> /// </returns>
public static Task<JToken> LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default) public static Task<JToken> LoadAsync(JsonReader reader, JsonLoadSettings settings, CancellationToken cancellationToken = default)
{ {
return ReadFromAsync(reader, settings, cancellationToken); return ReadFromAsync(reader, settings, cancellationToken);
} }

File diff suppressed because it is too large Load Diff

View File

@ -34,14 +34,14 @@ namespace LC.Newtonsoft.Json.Linq
public class JTokenReader : JsonReader, IJsonLineInfo public class JTokenReader : JsonReader, IJsonLineInfo
{ {
private readonly JToken _root; private readonly JToken _root;
private string? _initialPath; private string _initialPath;
private JToken? _parent; private JToken _parent;
private JToken? _current; private JToken _current;
/// <summary> /// <summary>
/// Gets the <see cref="JToken"/> at the reader's current position. /// Gets the <see cref="JToken"/> at the reader's current position.
/// </summary> /// </summary>
public JToken? CurrentToken => _current; public JToken CurrentToken => _current;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="JTokenReader"/> class. /// Initializes a new instance of the <see cref="JTokenReader"/> class.
@ -90,12 +90,6 @@ namespace LC.Newtonsoft.Json.Linq
} }
} }
// The current value could already be the root value if it is a comment
if (_current == _root)
{
return false;
}
_current = _root; _current = _root;
SetToken(_current); SetToken(_current);
return true; return true;
@ -108,8 +102,8 @@ namespace LC.Newtonsoft.Json.Linq
return ReadToEnd(); return ReadToEnd();
} }
JToken? next = t.Next; JToken next = t.Next;
if ((next == null || next == t) || t == t.Parent!.Last) if ((next == null || next == t) || t == t.Parent.Last)
{ {
if (t.Parent == null) if (t.Parent == null)
{ {
@ -152,7 +146,7 @@ namespace LC.Newtonsoft.Json.Linq
private bool ReadInto(JContainer c) private bool ReadInto(JContainer c)
{ {
JToken? firstChild = c.First; JToken firstChild = c.First;
if (firstChild == null) if (firstChild == null)
{ {
return SetEnd(c); return SetEnd(c);
@ -221,7 +215,7 @@ namespace LC.Newtonsoft.Json.Linq
break; break;
case JTokenType.Date: case JTokenType.Date:
{ {
object? v = ((JValue)token).Value; object v = ((JValue)token).Value;
if (v is DateTime dt) if (v is DateTime dt)
{ {
v = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); v = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
@ -241,7 +235,7 @@ namespace LC.Newtonsoft.Json.Linq
break; break;
case JTokenType.Uri: case JTokenType.Uri:
{ {
object? v = ((JValue)token).Value; object v = ((JValue)token).Value;
SetToken(JsonToken.String, v is Uri uri ? uri.OriginalString : SafeToString(v)); SetToken(JsonToken.String, v is Uri uri ? uri.OriginalString : SafeToString(v));
break; break;
} }
@ -253,7 +247,7 @@ namespace LC.Newtonsoft.Json.Linq
} }
} }
private string? SafeToString(object? value) private string SafeToString(object value)
{ {
return value?.ToString(); return value?.ToString();
} }
@ -265,7 +259,7 @@ namespace LC.Newtonsoft.Json.Linq
return false; return false;
} }
IJsonLineInfo? info = _current; IJsonLineInfo info = _current;
return (info != null && info.HasLineInfo()); return (info != null && info.HasLineInfo());
} }
@ -278,7 +272,7 @@ namespace LC.Newtonsoft.Json.Linq
return 0; return 0;
} }
IJsonLineInfo? info = _current; IJsonLineInfo info = _current;
if (info != null) if (info != null)
{ {
return info.LineNumber; return info.LineNumber;
@ -297,7 +291,7 @@ namespace LC.Newtonsoft.Json.Linq
return 0; return 0;
} }
IJsonLineInfo? info = _current; IJsonLineInfo info = _current;
if (info != null) if (info != null)
{ {
return info.LinePosition; return info.LinePosition;
@ -321,9 +315,9 @@ namespace LC.Newtonsoft.Json.Linq
_initialPath = _root.Path; _initialPath = _root.Path;
} }
if (!StringUtils.IsNullOrEmpty(_initialPath)) if (!string.IsNullOrEmpty(_initialPath))
{ {
if (StringUtils.IsNullOrEmpty(path)) if (string.IsNullOrEmpty(path))
{ {
return _initialPath; return _initialPath;
} }

View File

@ -24,7 +24,6 @@
#endregion #endregion
using System; using System;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
#if HAVE_BIG_INTEGER #if HAVE_BIG_INTEGER
using System.Numerics; using System.Numerics;
@ -38,22 +37,22 @@ namespace LC.Newtonsoft.Json.Linq
/// </summary> /// </summary>
public partial class JTokenWriter : JsonWriter public partial class JTokenWriter : JsonWriter
{ {
private JContainer? _token; private JContainer _token;
private JContainer? _parent; private JContainer _parent;
// used when writer is writing single value and the value has no containing parent // used when writer is writing single value and the value has no containing parent
private JValue? _value; private JValue _value;
private JToken? _current; private JToken _current;
/// <summary> /// <summary>
/// Gets the <see cref="JToken"/> at the writer's current position. /// Gets the <see cref="JToken"/> at the writer's current position.
/// </summary> /// </summary>
public JToken? CurrentToken => _current; public JToken CurrentToken => _current;
/// <summary> /// <summary>
/// Gets the token being written. /// Gets the token being written.
/// </summary> /// </summary>
/// <value>The token being written.</value> /// <value>The token being written.</value>
public JToken? Token public JToken Token
{ {
get get
{ {
@ -132,7 +131,7 @@ namespace LC.Newtonsoft.Json.Linq
private void RemoveParent() private void RemoveParent()
{ {
_current = _parent; _current = _parent;
_parent = _parent!.Parent; _parent = _parent.Parent;
if (_parent != null && _parent.Type == JTokenType.Property) if (_parent != null && _parent.Type == JTokenType.Property)
{ {
@ -187,26 +186,21 @@ namespace LC.Newtonsoft.Json.Linq
base.WritePropertyName(name); base.WritePropertyName(name);
} }
private void AddValue(object? value, JsonToken token) private void AddValue(object value, JsonToken token)
{ {
AddValue(new JValue(value), token); AddValue(new JValue(value), token);
} }
internal void AddValue(JValue? value, JsonToken token) internal void AddValue(JValue value, JsonToken token)
{ {
if (_parent != null) if (_parent != null)
{ {
// TryAdd will return false if an invalid JToken type is added. _parent.Add(value);
// For example, a JComment can't be added to a JObject. _current = _parent.Last;
// If there is an invalid JToken type then skip it.
if (_parent.TryAdd(value))
{
_current = _parent.Last;
if (_parent.Type == JTokenType.Property) if (_parent.Type == JTokenType.Property)
{ {
_parent = _parent.Parent; _parent = _parent.Parent;
}
} }
} }
else else
@ -222,7 +216,7 @@ namespace LC.Newtonsoft.Json.Linq
/// An error will be raised if the value cannot be written as a single JSON token. /// An error will be raised if the value cannot be written as a single JSON token.
/// </summary> /// </summary>
/// <param name="value">The <see cref="Object"/> value to write.</param> /// <param name="value">The <see cref="Object"/> value to write.</param>
public override void WriteValue(object? value) public override void WriteValue(object value)
{ {
#if HAVE_BIG_INTEGER #if HAVE_BIG_INTEGER
if (value is BigInteger) if (value is BigInteger)
@ -259,7 +253,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Writes raw JSON. /// Writes raw JSON.
/// </summary> /// </summary>
/// <param name="json">The raw JSON to write.</param> /// <param name="json">The raw JSON to write.</param>
public override void WriteRaw(string? json) public override void WriteRaw(string json)
{ {
base.WriteRaw(json); base.WriteRaw(json);
AddValue(new JRaw(json), JsonToken.Raw); AddValue(new JRaw(json), JsonToken.Raw);
@ -269,7 +263,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Writes a comment <c>/*...*/</c> containing the specified text. /// Writes a comment <c>/*...*/</c> containing the specified text.
/// </summary> /// </summary>
/// <param name="text">Text to place inside the comment.</param> /// <param name="text">Text to place inside the comment.</param>
public override void WriteComment(string? text) public override void WriteComment(string text)
{ {
base.WriteComment(text); base.WriteComment(text);
AddValue(JValue.CreateComment(text), JsonToken.Comment); AddValue(JValue.CreateComment(text), JsonToken.Comment);
@ -279,7 +273,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Writes a <see cref="String"/> value. /// Writes a <see cref="String"/> value.
/// </summary> /// </summary>
/// <param name="value">The <see cref="String"/> value to write.</param> /// <param name="value">The <see cref="String"/> value to write.</param>
public override void WriteValue(string? value) public override void WriteValue(string value)
{ {
base.WriteValue(value); base.WriteValue(value);
AddValue(value, JsonToken.String); AddValue(value, JsonToken.String);
@ -452,7 +446,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Writes a <see cref="Byte"/>[] value. /// Writes a <see cref="Byte"/>[] value.
/// </summary> /// </summary>
/// <param name="value">The <see cref="Byte"/>[] value to write.</param> /// <param name="value">The <see cref="Byte"/>[] value to write.</param>
public override void WriteValue(byte[]? value) public override void WriteValue(byte[] value)
{ {
base.WriteValue(value); base.WriteValue(value);
AddValue(value, JsonToken.Bytes); AddValue(value, JsonToken.Bytes);
@ -482,7 +476,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Writes a <see cref="Uri"/> value. /// Writes a <see cref="Uri"/> value.
/// </summary> /// </summary>
/// <param name="value">The <see cref="Uri"/> value to write.</param> /// <param name="value">The <see cref="Uri"/> value to write.</param>
public override void WriteValue(Uri? value) public override void WriteValue(Uri value)
{ {
base.WriteValue(value); base.WriteValue(value);
AddValue(value, JsonToken.String); AddValue(value, JsonToken.String);
@ -502,7 +496,7 @@ namespace LC.Newtonsoft.Json.Linq
} }
} }
JToken value = tokenReader.CurrentToken!.CloneToken(); JToken value = tokenReader.CurrentToken.CloneToken();
if (_parent != null) if (_parent != null)
{ {

View File

@ -49,7 +49,7 @@ namespace LC.Newtonsoft.Json.Linq
{ {
if (converters != null && converters.Length > 0 && _value != null) if (converters != null && converters.Length > 0 && _value != null)
{ {
JsonConverter? matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType()); JsonConverter matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType());
if (matchingConverter != null && matchingConverter.CanWrite) if (matchingConverter != null && matchingConverter.CanWrite)
{ {
// TODO: Call WriteJsonAsync when it exists. // TODO: Call WriteJsonAsync when it exists.
@ -121,13 +121,13 @@ namespace LC.Newtonsoft.Json.Linq
return writer.WriteValueAsync(Convert.ToDateTime(_value, CultureInfo.InvariantCulture), cancellationToken); return writer.WriteValueAsync(Convert.ToDateTime(_value, CultureInfo.InvariantCulture), cancellationToken);
case JTokenType.Bytes: case JTokenType.Bytes:
return writer.WriteValueAsync((byte[]?)_value, cancellationToken); return writer.WriteValueAsync((byte[])_value, cancellationToken);
case JTokenType.Guid: case JTokenType.Guid:
return writer.WriteValueAsync(_value != null ? (Guid?)_value : null, cancellationToken); return writer.WriteValueAsync(_value != null ? (Guid?)_value : null, cancellationToken);
case JTokenType.TimeSpan: case JTokenType.TimeSpan:
return writer.WriteValueAsync(_value != null ? (TimeSpan?)_value : null, cancellationToken); return writer.WriteValueAsync(_value != null ? (TimeSpan?)_value : null, cancellationToken);
case JTokenType.Uri: case JTokenType.Uri:
return writer.WriteValueAsync((Uri?)_value, cancellationToken); return writer.WriteValueAsync((Uri)_value, cancellationToken);
} }
throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(Type), _valueType, "Unexpected token type."); throw MiscellaneousUtils.CreateArgumentOutOfRangeException(nameof(Type), _valueType, "Unexpected token type.");

View File

@ -28,8 +28,6 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using System.Globalization; using System.Globalization;
using System.Runtime.CompilerServices;
using System.Diagnostics.CodeAnalysis;
#if HAVE_DYNAMIC #if HAVE_DYNAMIC
using System.Dynamic; using System.Dynamic;
using System.Linq.Expressions; using System.Linq.Expressions;
@ -49,9 +47,9 @@ namespace LC.Newtonsoft.Json.Linq
#endif #endif
{ {
private JTokenType _valueType; private JTokenType _valueType;
private object? _value; private object _value;
internal JValue(object? value, JTokenType type) internal JValue(object value, JTokenType type)
{ {
_value = value; _value = value;
_valueType = type; _valueType = type;
@ -64,7 +62,6 @@ namespace LC.Newtonsoft.Json.Linq
public JValue(JValue other) public JValue(JValue other)
: this(other.Value, other.Type) : this(other.Value, other.Type)
{ {
CopyAnnotations(this, other);
} }
/// <summary> /// <summary>
@ -155,7 +152,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Initializes a new instance of the <see cref="JValue"/> class with the given value. /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
/// </summary> /// </summary>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
public JValue(string? value) public JValue(string value)
: this(value, JTokenType.String) : this(value, JTokenType.String)
{ {
} }
@ -173,7 +170,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Initializes a new instance of the <see cref="JValue"/> class with the given value. /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
/// </summary> /// </summary>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
public JValue(Uri? value) public JValue(Uri value)
: this(value, (value != null) ? JTokenType.Uri : JTokenType.Null) : this(value, (value != null) ? JTokenType.Uri : JTokenType.Null)
{ {
} }
@ -191,7 +188,7 @@ namespace LC.Newtonsoft.Json.Linq
/// Initializes a new instance of the <see cref="JValue"/> class with the given value. /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
/// </summary> /// </summary>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
public JValue(object? value) public JValue(object value)
: this(value, GetValueType(null, value)) : this(value, GetValueType(null, value))
{ {
} }
@ -244,7 +241,7 @@ namespace LC.Newtonsoft.Json.Linq
} }
#endif #endif
internal static int Compare(JTokenType valueType, object? objA, object? objB) internal static int Compare(JTokenType valueType, object objA, object objB)
{ {
if (objA == objB) if (objA == objB)
{ {
@ -270,8 +267,8 @@ namespace LC.Newtonsoft.Json.Linq
} }
if (objB is BigInteger integerB) if (objB is BigInteger integerB)
{ {
return -CompareBigInteger(integerB, objA); return -CompareBigInteger(integerB, objA);
} }
#endif #endif
if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) if (objA is ulong || objB is ulong || objA is decimal || objB is decimal)
{ {
@ -303,7 +300,7 @@ namespace LC.Newtonsoft.Json.Linq
return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToDecimal(objB, CultureInfo.InvariantCulture)); return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToDecimal(objB, CultureInfo.InvariantCulture));
} }
return CompareFloat(objA, objB); return CompareFloat(objA, objB);
} }
case JTokenType.Comment: case JTokenType.Comment:
case JTokenType.String: case JTokenType.String:
case JTokenType.Raw: case JTokenType.Raw:
@ -356,10 +353,10 @@ namespace LC.Newtonsoft.Json.Linq
throw new ArgumentException("Object must be of type byte[]."); throw new ArgumentException("Object must be of type byte[].");
} }
byte[]? bytesA = objA as byte[]; byte[] bytesA = objA as byte[];
MiscellaneousUtils.Assert(bytesA != null); Debug.Assert(bytesA != null);
return MiscellaneousUtils.ByteArrayCompare(bytesA!, bytesB); return MiscellaneousUtils.ByteArrayCompare(bytesA, bytesB);
case JTokenType.Guid: case JTokenType.Guid:
if (!(objB is Guid)) if (!(objB is Guid))
{ {
@ -371,7 +368,7 @@ namespace LC.Newtonsoft.Json.Linq
return guid1.CompareTo(guid2); return guid1.CompareTo(guid2);
case JTokenType.Uri: case JTokenType.Uri:
Uri? uri2 = objB as Uri; Uri uri2 = objB as Uri;
if (uri2 == null) if (uri2 == null)
{ {
throw new ArgumentException("Object must be of type Uri."); throw new ArgumentException("Object must be of type Uri.");
@ -410,7 +407,7 @@ namespace LC.Newtonsoft.Json.Linq
} }
#if HAVE_EXPRESSIONS #if HAVE_EXPRESSIONS
private static bool Operation(ExpressionType operation, object? objA, object? objB, out object? result) private static bool Operation(ExpressionType operation, object objA, object objB, out object result)
{ {
if (objA is string || objB is string) if (objA is string || objB is string)
{ {
@ -567,7 +564,7 @@ namespace LC.Newtonsoft.Json.Linq
/// </summary> /// </summary>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <returns>A <see cref="JValue"/> comment with the given value.</returns> /// <returns>A <see cref="JValue"/> comment with the given value.</returns>
public static JValue CreateComment(string? value) public static JValue CreateComment(string value)
{ {
return new JValue(value, JTokenType.Comment); return new JValue(value, JTokenType.Comment);
} }
@ -577,7 +574,7 @@ namespace LC.Newtonsoft.Json.Linq
/// </summary> /// </summary>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <returns>A <see cref="JValue"/> string with the given value.</returns> /// <returns>A <see cref="JValue"/> string with the given value.</returns>
public static JValue CreateString(string? value) public static JValue CreateString(string value)
{ {
return new JValue(value, JTokenType.String); return new JValue(value, JTokenType.String);
} }
@ -600,7 +597,7 @@ namespace LC.Newtonsoft.Json.Linq
return new JValue(null, JTokenType.Undefined); return new JValue(null, JTokenType.Undefined);
} }
private static JTokenType GetValueType(JTokenType? current, object? value) private static JTokenType GetValueType(JTokenType? current, object value)
{ {
if (value == null) if (value == null)
{ {
@ -697,13 +694,13 @@ namespace LC.Newtonsoft.Json.Linq
/// Gets or sets the underlying token value. /// Gets or sets the underlying token value.
/// </summary> /// </summary>
/// <value>The underlying token value.</value> /// <value>The underlying token value.</value>
public object? Value public object Value
{ {
get => _value; get => _value;
set set
{ {
Type? currentType = _value?.GetType(); Type currentType = _value?.GetType();
Type? newType = value?.GetType(); Type newType = value?.GetType();
if (currentType != newType) if (currentType != newType)
{ {
@ -723,7 +720,7 @@ namespace LC.Newtonsoft.Json.Linq
{ {
if (converters != null && converters.Length > 0 && _value != null) if (converters != null && converters.Length > 0 && _value != null)
{ {
JsonConverter? matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType()); JsonConverter matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType());
if (matchingConverter != null && matchingConverter.CanWrite) if (matchingConverter != null && matchingConverter.CanWrite)
{ {
matchingConverter.WriteJson(writer, _value, JsonSerializer.CreateDefault()); matchingConverter.WriteJson(writer, _value, JsonSerializer.CreateDefault());
@ -806,7 +803,7 @@ namespace LC.Newtonsoft.Json.Linq
} }
return; return;
case JTokenType.Bytes: case JTokenType.Bytes:
writer.WriteValue((byte[]?)_value); writer.WriteValue((byte[])_value);
return; return;
case JTokenType.Guid: case JTokenType.Guid:
writer.WriteValue((_value != null) ? (Guid?)_value : null); writer.WriteValue((_value != null) ? (Guid?)_value : null);
@ -815,7 +812,7 @@ namespace LC.Newtonsoft.Json.Linq
writer.WriteValue((_value != null) ? (TimeSpan?)_value : null); writer.WriteValue((_value != null) ? (TimeSpan?)_value : null);
return; return;
case JTokenType.Uri: case JTokenType.Uri:
writer.WriteValue((Uri?)_value); writer.WriteValue((Uri)_value);
return; return;
} }
@ -842,7 +839,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <c>true</c> if the current object is equal to the <paramref name="other"/> parameter; otherwise, <c>false</c>. /// <c>true</c> if the current object is equal to the <paramref name="other"/> parameter; otherwise, <c>false</c>.
/// </returns> /// </returns>
/// <param name="other">An object to compare with this object.</param> /// <param name="other">An object to compare with this object.</param>
public bool Equals(JValue? other) public bool Equals(JValue other)
{ {
if (other == null) if (other == null)
{ {
@ -861,12 +858,7 @@ namespace LC.Newtonsoft.Json.Linq
/// </returns> /// </returns>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (obj is JValue v) return Equals(obj as JValue);
{
return Equals(v);
}
return false;
} }
/// <summary> /// <summary>
@ -888,10 +880,6 @@ namespace LC.Newtonsoft.Json.Linq
/// <summary> /// <summary>
/// Returns a <see cref="String"/> that represents this instance. /// Returns a <see cref="String"/> that represents this instance.
/// </summary> /// </summary>
/// <remarks>
/// <c>ToString()</c> returns a non-JSON string value for tokens with a type of <see cref="JTokenType.String"/>.
/// If you want the JSON for all token types then you should use <see cref="WriteTo(JsonWriter, JsonConverter[])"/>.
/// </remarks>
/// <returns> /// <returns>
/// A <see cref="String"/> that represents this instance. /// A <see cref="String"/> that represents this instance.
/// </returns> /// </returns>
@ -937,7 +925,7 @@ namespace LC.Newtonsoft.Json.Linq
/// <returns> /// <returns>
/// A <see cref="String"/> that represents this instance. /// A <see cref="String"/> that represents this instance.
/// </returns> /// </returns>
public string ToString(string? format, IFormatProvider formatProvider) public string ToString(string format, IFormatProvider formatProvider)
{ {
if (_value == null) if (_value == null)
{ {
@ -969,7 +957,7 @@ namespace LC.Newtonsoft.Json.Linq
private class JValueDynamicProxy : DynamicProxy<JValue> private class JValueDynamicProxy : DynamicProxy<JValue>
{ {
public override bool TryConvert(JValue instance, ConvertBinder binder, [NotNullWhen(true)]out object? result) public override bool TryConvert(JValue instance, ConvertBinder binder, out object result)
{ {
if (binder.Type == typeof(JValue) || binder.Type == typeof(JToken)) if (binder.Type == typeof(JValue) || binder.Type == typeof(JToken))
{ {
@ -977,7 +965,7 @@ namespace LC.Newtonsoft.Json.Linq
return true; return true;
} }
object? value = instance.Value; object value = instance.Value;
if (value == null) if (value == null)
{ {
@ -989,9 +977,9 @@ namespace LC.Newtonsoft.Json.Linq
return true; return true;
} }
public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder binder, object arg, [NotNullWhen(true)]out object? result) public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder binder, object arg, out object result)
{ {
object? compareValue = arg is JValue value ? value.Value : arg; object compareValue = arg is JValue value ? value.Value : arg;
switch (binder.Operation) switch (binder.Operation)
{ {
@ -1043,7 +1031,7 @@ namespace LC.Newtonsoft.Json.Linq
} }
JTokenType comparisonType; JTokenType comparisonType;
object? otherValue; object otherValue;
if (obj is JValue value) if (obj is JValue value)
{ {
otherValue = value.Value; otherValue = value.Value;
@ -1178,7 +1166,7 @@ namespace LC.Newtonsoft.Json.Linq
return (DateTime)this; return (DateTime)this;
} }
object? IConvertible.ToType(Type conversionType, IFormatProvider provider) object IConvertible.ToType(Type conversionType, IFormatProvider provider)
{ {
return ToObject(conversionType); return ToObject(conversionType);
} }

View File

@ -8,13 +8,13 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
public int? Index { get; set; } public int? Index { get; set; }
public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, JsonSelectSettings? settings) public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, bool errorWhenNoMatch)
{ {
foreach (JToken t in current) foreach (JToken t in current)
{ {
if (Index != null) if (Index != null)
{ {
JToken? v = GetTokenIndex(t, settings, Index.GetValueOrDefault()); JToken v = GetTokenIndex(t, errorWhenNoMatch, Index.GetValueOrDefault());
if (v != null) if (v != null)
{ {
@ -32,7 +32,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
} }
else else
{ {
if (settings?.ErrorWhenNoMatch ?? false) if (errorWhenNoMatch)
{ {
throw new JsonException("Index * not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, t.GetType().Name)); throw new JsonException("Index * not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, t.GetType().Name));
} }

View File

@ -4,20 +4,15 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
internal class ArrayMultipleIndexFilter : PathFilter internal class ArrayMultipleIndexFilter : PathFilter
{ {
internal List<int> Indexes; public List<int> Indexes { get; set; }
public ArrayMultipleIndexFilter(List<int> indexes) public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, bool errorWhenNoMatch)
{
Indexes = indexes;
}
public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, JsonSelectSettings? settings)
{ {
foreach (JToken t in current) foreach (JToken t in current)
{ {
foreach (int i in Indexes) foreach (int i in Indexes)
{ {
JToken? v = GetTokenIndex(t, settings, i); JToken v = GetTokenIndex(t, errorWhenNoMatch, i);
if (v != null) if (v != null)
{ {

View File

@ -11,7 +11,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
public int? End { get; set; } public int? End { get; set; }
public int? Step { get; set; } public int? Step { get; set; }
public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, JsonSelectSettings? settings) public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, bool errorWhenNoMatch)
{ {
if (Step == 0) if (Step == 0)
{ {
@ -56,7 +56,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
} }
else else
{ {
if (settings?.ErrorWhenNoMatch ?? false) if (errorWhenNoMatch)
{ {
throw new JsonException("Array slice of {0} to {1} returned no results.".FormatWith(CultureInfo.InvariantCulture, throw new JsonException("Array slice of {0} to {1} returned no results.".FormatWith(CultureInfo.InvariantCulture,
Start != null ? Start.GetValueOrDefault().ToString(CultureInfo.InvariantCulture) : "*", Start != null ? Start.GetValueOrDefault().ToString(CultureInfo.InvariantCulture) : "*",
@ -66,7 +66,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
} }
else else
{ {
if (settings?.ErrorWhenNoMatch ?? false) if (errorWhenNoMatch)
{ {
throw new JsonException("Array slice is not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, t.GetType().Name)); throw new JsonException("Array slice is not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, t.GetType().Name));
} }

View File

@ -6,14 +6,9 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
internal class FieldFilter : PathFilter internal class FieldFilter : PathFilter
{ {
internal string? Name; public string Name { get; set; }
public FieldFilter(string? name) public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, bool errorWhenNoMatch)
{
Name = name;
}
public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, JsonSelectSettings? settings)
{ {
foreach (JToken t in current) foreach (JToken t in current)
{ {
@ -21,28 +16,28 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
if (Name != null) if (Name != null)
{ {
JToken? v = o[Name]; JToken v = o[Name];
if (v != null) if (v != null)
{ {
yield return v; yield return v;
} }
else if (settings?.ErrorWhenNoMatch ?? false) else if (errorWhenNoMatch)
{ {
throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, Name)); throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, Name));
} }
} }
else else
{ {
foreach (KeyValuePair<string, JToken?> p in o) foreach (KeyValuePair<string, JToken> p in o)
{ {
yield return p.Value!; yield return p.Value;
} }
} }
} }
else else
{ {
if (settings?.ErrorWhenNoMatch ?? false) if (errorWhenNoMatch)
{ {
throw new JsonException("Property '{0}' not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, Name ?? "*", t.GetType().Name)); throw new JsonException("Property '{0}' not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, Name ?? "*", t.GetType().Name));
} }

View File

@ -11,14 +11,9 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
internal class FieldMultipleFilter : PathFilter internal class FieldMultipleFilter : PathFilter
{ {
internal List<string> Names; public List<string> Names { get; set; }
public FieldMultipleFilter(List<string> names) public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, bool errorWhenNoMatch)
{
Names = names;
}
public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, JsonSelectSettings? settings)
{ {
foreach (JToken t in current) foreach (JToken t in current)
{ {
@ -26,14 +21,14 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
foreach (string name in Names) foreach (string name in Names)
{ {
JToken? v = o[name]; JToken v = o[name];
if (v != null) if (v != null)
{ {
yield return v; yield return v;
} }
if (settings?.ErrorWhenNoMatch ?? false) if (errorWhenNoMatch)
{ {
throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, name)); throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, name));
} }
@ -41,7 +36,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
} }
else else
{ {
if (settings?.ErrorWhenNoMatch ?? false) if (errorWhenNoMatch)
{ {
throw new JsonException("Properties {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", Names.Select(n => "'" + n + "'") throw new JsonException("Properties {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", Names.Select(n => "'" + n + "'")
#if !HAVE_STRING_JOIN_WITH_ENUMERABLE #if !HAVE_STRING_JOIN_WITH_ENUMERABLE

View File

@ -107,7 +107,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
case '(': case '(':
if (_currentIndex > currentPartStartIndex) if (_currentIndex > currentPartStartIndex)
{ {
string? member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex); string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex);
if (member == "*") if (member == "*")
{ {
member = null; member = null;
@ -118,8 +118,6 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
} }
filters.Add(ParseIndexer(currentChar, scan)); filters.Add(ParseIndexer(currentChar, scan));
scan = false;
_currentIndex++; _currentIndex++;
currentPartStartIndex = _currentIndex; currentPartStartIndex = _currentIndex;
followingIndexer = true; followingIndexer = true;
@ -138,7 +136,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
case '.': case '.':
if (_currentIndex > currentPartStartIndex) if (_currentIndex > currentPartStartIndex)
{ {
string? member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex); string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex);
if (member == "*") if (member == "*")
{ {
member = null; member = null;
@ -179,7 +177,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
if (_currentIndex > currentPartStartIndex) if (_currentIndex > currentPartStartIndex)
{ {
string? member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex).TrimEnd(); string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex).TrimEnd();
if (member == "*") if (member == "*")
{ {
member = null; member = null;
@ -198,9 +196,9 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
return atPathEnd; return atPathEnd;
} }
private static PathFilter CreatePathFilter(string? member, bool scan) private static PathFilter CreatePathFilter(string member, bool scan)
{ {
PathFilter filter = (scan) ? (PathFilter)new ScanFilter(member) : new FieldFilter(member); PathFilter filter = (scan) ? (PathFilter)new ScanFilter {Name = member} : new FieldFilter {Name = member};
return filter; return filter;
} }
@ -232,7 +230,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
int start = _currentIndex; int start = _currentIndex;
int? end = null; int? end = null;
List<int>? indexes = null; List<int> indexes = null;
int colonCount = 0; int colonCount = 0;
int? startIndex = null; int? startIndex = null;
int? endIndex = null; int? endIndex = null;
@ -264,7 +262,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
int index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture); int index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture);
indexes.Add(index); indexes.Add(index);
return new ArrayMultipleIndexFilter(indexes); return new ArrayMultipleIndexFilter { Indexes = indexes };
} }
else if (colonCount > 0) else if (colonCount > 0)
{ {
@ -423,19 +421,26 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
if (!scan) if (!scan)
{ {
return new QueryFilter(expression); return new QueryFilter
{
Expression = expression
};
} }
else else
{ {
return new QueryScanFilter(expression); return new QueryScanFilter
{
Expression = expression
};
} }
} }
private bool TryParseExpression(out List<PathFilter>? expressionPath) private bool TryParseExpression(out List<PathFilter> expressionPath)
{ {
if (_expression[_currentIndex] == '$') if (_expression[_currentIndex] == '$')
{ {
expressionPath = new List<PathFilter> { RootFilter.Instance }; expressionPath = new List<PathFilter>();
expressionPath.Add(RootFilter.Instance);
} }
else if (_expression[_currentIndex] == '@') else if (_expression[_currentIndex] == '@')
{ {
@ -449,7 +454,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
_currentIndex++; _currentIndex++;
if (ParsePath(expressionPath!, _currentIndex, true)) if (ParsePath(expressionPath, _currentIndex, true))
{ {
throw new JsonException("Path ended with open query."); throw new JsonException("Path ended with open query.");
} }
@ -466,12 +471,12 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
EatWhitespace(); EatWhitespace();
if (TryParseExpression(out List<PathFilter>? expressionPath)) if (TryParseExpression(out var expressionPath))
{ {
EatWhitespace(); EatWhitespace();
EnsureLength("Path ended with open query."); EnsureLength("Path ended with open query.");
return expressionPath!; return expressionPath;
} }
if (TryParseValue(out var value)) if (TryParseValue(out var value))
@ -487,13 +492,13 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
private QueryExpression ParseExpression() private QueryExpression ParseExpression()
{ {
QueryExpression? rootExpression = null; QueryExpression rootExpression = null;
CompositeExpression? parentExpression = null; CompositeExpression parentExpression = null;
while (_currentIndex < _expression.Length) while (_currentIndex < _expression.Length)
{ {
object left = ParseSide(); object left = ParseSide();
object? right = null; object right = null;
QueryOperator op; QueryOperator op;
if (_expression[_currentIndex] == ')' if (_expression[_currentIndex] == ')'
@ -509,14 +514,19 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
right = ParseSide(); right = ParseSide();
} }
BooleanQueryExpression booleanExpression = new BooleanQueryExpression(op, left, right); BooleanQueryExpression booleanExpression = new BooleanQueryExpression
{
Left = left,
Operator = op,
Right = right
};
if (_expression[_currentIndex] == ')') if (_expression[_currentIndex] == ')')
{ {
if (parentExpression != null) if (parentExpression != null)
{ {
parentExpression.Expressions.Add(booleanExpression); parentExpression.Expressions.Add(booleanExpression);
return rootExpression!; return rootExpression;
} }
return booleanExpression; return booleanExpression;
@ -530,7 +540,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
if (parentExpression == null || parentExpression.Operator != QueryOperator.And) if (parentExpression == null || parentExpression.Operator != QueryOperator.And)
{ {
CompositeExpression andExpression = new CompositeExpression(QueryOperator.And); CompositeExpression andExpression = new CompositeExpression { Operator = QueryOperator.And };
parentExpression?.Expressions.Add(andExpression); parentExpression?.Expressions.Add(andExpression);
@ -553,7 +563,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
if (parentExpression == null || parentExpression.Operator != QueryOperator.Or) if (parentExpression == null || parentExpression.Operator != QueryOperator.Or)
{ {
CompositeExpression orExpression = new CompositeExpression(QueryOperator.Or); CompositeExpression orExpression = new CompositeExpression { Operator = QueryOperator.Or };
parentExpression?.Expressions.Add(orExpression); parentExpression?.Expressions.Add(orExpression);
@ -572,7 +582,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
throw new JsonException("Path ended with open query."); throw new JsonException("Path ended with open query.");
} }
private bool TryParseValue(out object? value) private bool TryParseValue(out object value)
{ {
char currentChar = _expression[_currentIndex]; char currentChar = _expression[_currentIndex];
if (currentChar == '\'') if (currentChar == '\'')
@ -753,9 +763,9 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
private bool Match(string s) private bool Match(string s)
{ {
int currentPosition = _currentIndex; int currentPosition = _currentIndex;
for (int i = 0; i < s.Length; i++) foreach (char c in s)
{ {
if (currentPosition < _expression.Length && _expression[currentPosition] == s[i]) if (currentPosition < _expression.Length && _expression[currentPosition] == c)
{ {
currentPosition++; currentPosition++;
} }
@ -822,7 +832,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
private PathFilter ParseQuotedField(char indexerCloseChar, bool scan) private PathFilter ParseQuotedField(char indexerCloseChar, bool scan)
{ {
List<string>? fields = null; List<string> fields = null;
while (_currentIndex < _expression.Length) while (_currentIndex < _expression.Length)
{ {
@ -837,8 +847,8 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
fields.Add(field); fields.Add(field);
return (scan) return (scan)
? (PathFilter)new ScanMultipleFilter(fields) ? (PathFilter)new ScanMultipleFilter { Names = fields }
: (PathFilter)new FieldMultipleFilter(fields); : (PathFilter)new FieldMultipleFilter { Names = fields };
} }
else else
{ {
@ -874,17 +884,17 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
} }
} }
internal IEnumerable<JToken> Evaluate(JToken root, JToken t, JsonSelectSettings? settings) internal IEnumerable<JToken> Evaluate(JToken root, JToken t, bool errorWhenNoMatch)
{ {
return Evaluate(Filters, root, t, settings); return Evaluate(Filters, root, t, errorWhenNoMatch);
} }
internal static IEnumerable<JToken> Evaluate(List<PathFilter> filters, JToken root, JToken t, JsonSelectSettings? settings) internal static IEnumerable<JToken> Evaluate(List<PathFilter> filters, JToken root, JToken t, bool errorWhenNoMatch)
{ {
IEnumerable<JToken> current = new[] { t }; IEnumerable<JToken> current = new[] { t };
foreach (PathFilter filter in filters) foreach (PathFilter filter in filters)
{ {
current = filter.ExecuteFilter(root, current, settings); current = filter.ExecuteFilter(root, current, errorWhenNoMatch);
} }
return current; return current;

View File

@ -6,15 +6,16 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
internal abstract class PathFilter internal abstract class PathFilter
{ {
public abstract IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, JsonSelectSettings? settings); public abstract IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, bool errorWhenNoMatch);
protected static JToken? GetTokenIndex(JToken t, JsonSelectSettings? settings, int index) protected static JToken GetTokenIndex(JToken t, bool errorWhenNoMatch, int index)
{ {
if (t is JArray a) if (t is JArray a)
{ {
if (a.Count <= index) if (a.Count <= index)
{ {
if (settings?.ErrorWhenNoMatch ?? false) if (errorWhenNoMatch)
{ {
throw new JsonException("Index {0} outside the bounds of JArray.".FormatWith(CultureInfo.InvariantCulture, index)); throw new JsonException("Index {0} outside the bounds of JArray.".FormatWith(CultureInfo.InvariantCulture, index));
} }
@ -28,7 +29,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
if (c.Count <= index) if (c.Count <= index)
{ {
if (settings?.ErrorWhenNoMatch ?? false) if (errorWhenNoMatch)
{ {
throw new JsonException("Index {0} outside the bounds of JConstructor.".FormatWith(CultureInfo.InvariantCulture, index)); throw new JsonException("Index {0} outside the bounds of JConstructor.".FormatWith(CultureInfo.InvariantCulture, index));
} }
@ -40,7 +41,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
} }
else else
{ {
if (settings?.ErrorWhenNoMatch ?? false) if (errorWhenNoMatch)
{ {
throw new JsonException("Index {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, index, t.GetType().Name)); throw new JsonException("Index {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, index, t.GetType().Name));
} }
@ -49,7 +50,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
} }
} }
protected static JToken? GetNextScanValue(JToken originalParent, JToken? container, JToken? value) protected static JToken GetNextScanValue(JToken originalParent, JToken container, JToken value)
{ {
// step into container's values // step into container's values
if (container != null && container.HasValues) if (container != null && container.HasValues)
@ -59,7 +60,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
else else
{ {
// finished container, move to parent // finished container, move to parent
while (value != null && value != originalParent && value == value.Parent!.Last) while (value != null && value != originalParent && value == value.Parent.Last)
{ {
value = value.Parent; value = value.Parent;
} }

View File

@ -32,39 +32,28 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
internal abstract class QueryExpression internal abstract class QueryExpression
{ {
internal QueryOperator Operator; public QueryOperator Operator { get; set; }
public QueryExpression(QueryOperator @operator) public abstract bool IsMatch(JToken root, JToken t);
{
Operator = @operator;
}
// For unit tests
public bool IsMatch(JToken root, JToken t)
{
return IsMatch(root, t, null);
}
public abstract bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings);
} }
internal class CompositeExpression : QueryExpression internal class CompositeExpression : QueryExpression
{ {
public List<QueryExpression> Expressions { get; set; } public List<QueryExpression> Expressions { get; set; }
public CompositeExpression(QueryOperator @operator) : base(@operator) public CompositeExpression()
{ {
Expressions = new List<QueryExpression>(); Expressions = new List<QueryExpression>();
} }
public override bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings) public override bool IsMatch(JToken root, JToken t)
{ {
switch (Operator) switch (Operator)
{ {
case QueryOperator.And: case QueryOperator.And:
foreach (QueryExpression e in Expressions) foreach (QueryExpression e in Expressions)
{ {
if (!e.IsMatch(root, t, settings)) if (!e.IsMatch(root, t))
{ {
return false; return false;
} }
@ -73,7 +62,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
case QueryOperator.Or: case QueryOperator.Or:
foreach (QueryExpression e in Expressions) foreach (QueryExpression e in Expressions)
{ {
if (e.IsMatch(root, t, settings)) if (e.IsMatch(root, t))
{ {
return true; return true;
} }
@ -87,16 +76,10 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
internal class BooleanQueryExpression : QueryExpression internal class BooleanQueryExpression : QueryExpression
{ {
public readonly object Left; public object Left { get; set; }
public readonly object? Right; public object Right { get; set; }
public BooleanQueryExpression(QueryOperator @operator, object left, object? right) : base(@operator) private IEnumerable<JToken> GetResult(JToken root, JToken t, object o)
{
Left = left;
Right = right;
}
private IEnumerable<JToken> GetResult(JToken root, JToken t, object? o)
{ {
if (o is JToken resultToken) if (o is JToken resultToken)
{ {
@ -105,13 +88,13 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
if (o is List<PathFilter> pathFilters) if (o is List<PathFilter> pathFilters)
{ {
return JPath.Evaluate(pathFilters, root, t, null); return JPath.Evaluate(pathFilters, root, t, false);
} }
return CollectionUtils.ArrayEmpty<JToken>(); return CollectionUtils.ArrayEmpty<JToken>();
} }
public override bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings) public override bool IsMatch(JToken root, JToken t)
{ {
if (Operator == QueryOperator.Exists) if (Operator == QueryOperator.Exists)
{ {
@ -130,7 +113,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
JToken leftResult = leftResults.Current; JToken leftResult = leftResults.Current;
foreach (JToken rightResult in rightResults) foreach (JToken rightResult in rightResults)
{ {
if (MatchTokens(leftResult, rightResult, settings)) if (MatchTokens(leftResult, rightResult))
{ {
return true; return true;
} }
@ -142,14 +125,14 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
return false; return false;
} }
private bool MatchTokens(JToken leftResult, JToken rightResult, JsonSelectSettings? settings) private bool MatchTokens(JToken leftResult, JToken rightResult)
{ {
if (leftResult is JValue leftValue && rightResult is JValue rightValue) if (leftResult is JValue leftValue && rightResult is JValue rightValue)
{ {
switch (Operator) switch (Operator)
{ {
case QueryOperator.RegexEquals: case QueryOperator.RegexEquals:
if (RegexEquals(leftValue, rightValue, settings)) if (RegexEquals(leftValue, rightValue))
{ {
return true; return true;
} }
@ -221,25 +204,20 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
return false; return false;
} }
private static bool RegexEquals(JValue input, JValue pattern, JsonSelectSettings? settings) private static bool RegexEquals(JValue input, JValue pattern)
{ {
if (input.Type != JTokenType.String || pattern.Type != JTokenType.String) if (input.Type != JTokenType.String || pattern.Type != JTokenType.String)
{ {
return false; return false;
} }
string regexText = (string)pattern.Value!; string regexText = (string)pattern.Value;
int patternOptionDelimiterIndex = regexText.LastIndexOf('/'); int patternOptionDelimiterIndex = regexText.LastIndexOf('/');
string patternText = regexText.Substring(1, patternOptionDelimiterIndex - 1); string patternText = regexText.Substring(1, patternOptionDelimiterIndex - 1);
string optionsText = regexText.Substring(patternOptionDelimiterIndex + 1); string optionsText = regexText.Substring(patternOptionDelimiterIndex + 1);
#if HAVE_REGEX_TIMEOUTS return Regex.IsMatch((string)input.Value, patternText, MiscellaneousUtils.GetRegexOptions(optionsText));
TimeSpan timeout = settings?.RegexMatchTimeout ?? Regex.InfiniteMatchTimeout;
return Regex.IsMatch((string)input.Value!, patternText, MiscellaneousUtils.GetRegexOptions(optionsText), timeout);
#else
return Regex.IsMatch((string)input.Value!, patternText, MiscellaneousUtils.GetRegexOptions(optionsText));
#endif
} }
internal static bool EqualsWithStringCoercion(JValue value, JValue queryValue) internal static bool EqualsWithStringCoercion(JValue value, JValue queryValue)
@ -262,7 +240,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
return false; return false;
} }
string queryValueString = (string)queryValue.Value!; string queryValueString = (string)queryValue.Value;
string currentValueString; string currentValueString;
@ -280,21 +258,21 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
else else
#endif #endif
{ {
DateTimeUtils.WriteDateTimeString(writer, (DateTime)value.Value!, DateFormatHandling.IsoDateFormat, null, CultureInfo.InvariantCulture); DateTimeUtils.WriteDateTimeString(writer, (DateTime)value.Value, DateFormatHandling.IsoDateFormat, null, CultureInfo.InvariantCulture);
} }
currentValueString = writer.ToString(); currentValueString = writer.ToString();
} }
break; break;
case JTokenType.Bytes: case JTokenType.Bytes:
currentValueString = Convert.ToBase64String((byte[])value.Value!); currentValueString = Convert.ToBase64String((byte[])value.Value);
break; break;
case JTokenType.Guid: case JTokenType.Guid:
case JTokenType.TimeSpan: case JTokenType.TimeSpan:
currentValueString = value.Value!.ToString(); currentValueString = value.Value.ToString();
break; break;
case JTokenType.Uri: case JTokenType.Uri:
currentValueString = ((Uri)value.Value!).OriginalString; currentValueString = ((Uri)value.Value).OriginalString;
break; break;
default: default:
return false; return false;
@ -305,8 +283,8 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
internal static bool EqualsWithStrictMatch(JValue value, JValue queryValue) internal static bool EqualsWithStrictMatch(JValue value, JValue queryValue)
{ {
MiscellaneousUtils.Assert(value != null); Debug.Assert(value != null);
MiscellaneousUtils.Assert(queryValue != null); Debug.Assert(queryValue != null);
// Handle comparing an integer with a float // Handle comparing an integer with a float
// e.g. Comparing 1 and 1.0 // e.g. Comparing 1 and 1.0

View File

@ -5,20 +5,15 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
internal class QueryFilter : PathFilter internal class QueryFilter : PathFilter
{ {
internal QueryExpression Expression; public QueryExpression Expression { get; set; }
public QueryFilter(QueryExpression expression) public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, bool errorWhenNoMatch)
{
Expression = expression;
}
public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, JsonSelectSettings? settings)
{ {
foreach (JToken t in current) foreach (JToken t in current)
{ {
foreach (JToken v in t) foreach (JToken v in t)
{ {
if (Expression.IsMatch(root, v, settings)) if (Expression.IsMatch(root, v))
{ {
yield return v; yield return v;
} }

View File

@ -5,14 +5,9 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
internal class QueryScanFilter : PathFilter internal class QueryScanFilter : PathFilter
{ {
internal QueryExpression Expression; public QueryExpression Expression { get; set; }
public QueryScanFilter(QueryExpression expression) public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, bool errorWhenNoMatch)
{
Expression = expression;
}
public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, JsonSelectSettings? settings)
{ {
foreach (JToken t in current) foreach (JToken t in current)
{ {
@ -20,7 +15,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
foreach (JToken d in c.DescendantsAndSelf()) foreach (JToken d in c.DescendantsAndSelf())
{ {
if (Expression.IsMatch(root, d, settings)) if (Expression.IsMatch(root, d))
{ {
yield return d; yield return d;
} }
@ -28,7 +23,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
} }
else else
{ {
if (Expression.IsMatch(root, t, settings)) if (Expression.IsMatch(root, t))
{ {
yield return t; yield return t;
} }

View File

@ -10,7 +10,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
} }
public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, JsonSelectSettings? settings) public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, bool errorWhenNoMatch)
{ {
return new[] { root }; return new[] { root };
} }

View File

@ -4,14 +4,9 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
internal class ScanFilter : PathFilter internal class ScanFilter : PathFilter
{ {
internal string? Name; public string Name { get; set; }
public ScanFilter(string? name) public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, bool errorWhenNoMatch)
{
Name = name;
}
public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, JsonSelectSettings? settings)
{ {
foreach (JToken c in current) foreach (JToken c in current)
{ {
@ -20,11 +15,11 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
yield return c; yield return c;
} }
JToken? value = c; JToken value = c;
while (true) while (true)
{ {
JContainer? container = value as JContainer; JContainer container = value as JContainer;
value = GetNextScanValue(c, container, value); value = GetNextScanValue(c, container, value);
if (value == null) if (value == null)

View File

@ -4,22 +4,17 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
{ {
internal class ScanMultipleFilter : PathFilter internal class ScanMultipleFilter : PathFilter
{ {
private List<string> _names; public List<string> Names { get; set; }
public ScanMultipleFilter(List<string> names) public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, bool errorWhenNoMatch)
{
_names = names;
}
public override IEnumerable<JToken> ExecuteFilter(JToken root, IEnumerable<JToken> current, JsonSelectSettings? settings)
{ {
foreach (JToken c in current) foreach (JToken c in current)
{ {
JToken? value = c; JToken value = c;
while (true) while (true)
{ {
JContainer? container = value as JContainer; JContainer container = value as JContainer;
value = GetNextScanValue(c, container, value); value = GetNextScanValue(c, container, value);
if (value == null) if (value == null)
@ -29,7 +24,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
if (value is JProperty property) if (value is JProperty property)
{ {
foreach (string name in _names) foreach (string name in Names)
{ {
if (property.Name == name) if (property.Name == name)
{ {
@ -37,6 +32,7 @@ namespace LC.Newtonsoft.Json.Linq.JsonPath
} }
} }
} }
} }
} }
} }

View File

@ -1,28 +0,0 @@
using System;
namespace LC.Newtonsoft.Json.Linq
{
/// <summary>
/// Specifies the settings used when selecting JSON.
/// </summary>
public class JsonSelectSettings
{
#if HAVE_REGEX_TIMEOUTS
/// <summary>
/// Gets or sets a timeout that will be used when executing regular expressions.
/// </summary>
/// <value>The timeout that will be used when executing regular expressions.</value>
public TimeSpan? RegexMatchTimeout { get; set; }
#endif
/// <summary>
/// Gets or sets a flag that indicates whether an error should be thrown if
/// no tokens are found when evaluating part of the expression.
/// </summary>
/// <value>
/// A flag that indicates whether an error should be thrown if
/// no tokens are found when evaluating part of the expression.
/// </value>
public bool ErrorWhenNoMatch { get; set; }
}
}

View File

@ -28,8 +28,6 @@ using System.Collections.Generic;
using LC.Newtonsoft.Json.Linq; using LC.Newtonsoft.Json.Linq;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
#nullable disable
namespace LC.Newtonsoft.Json.Schema namespace LC.Newtonsoft.Json.Schema
{ {
/// <summary> /// <summary>

View File

@ -30,8 +30,6 @@ using LC.Newtonsoft.Json.Linq;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using System.Globalization; using System.Globalization;
#nullable disable
namespace LC.Newtonsoft.Json.Schema namespace LC.Newtonsoft.Json.Schema
{ {
/// <summary> /// <summary>

View File

@ -35,8 +35,6 @@ using System.Globalization;
using LC.Newtonsoft.Json.Utilities; using LC.Newtonsoft.Json.Utilities;
using LC.Newtonsoft.Json.Linq; using LC.Newtonsoft.Json.Linq;
#nullable disable
namespace LC.Newtonsoft.Json.Schema namespace LC.Newtonsoft.Json.Schema
{ {
[Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")]
@ -221,7 +219,7 @@ namespace LC.Newtonsoft.Json.Schema
} }
string location = token.Path.Replace(".", "/").Replace("[", "/").Replace("]", string.Empty); string location = token.Path.Replace(".", "/").Replace("[", "/").Replace("]", string.Empty);
if (!StringUtils.IsNullOrEmpty(location)) if (!string.IsNullOrEmpty(location))
{ {
location = "/" + location; location = "/" + location;
} }

Some files were not shown because too many files have changed in this diff Show More