chore: 初始化北汽福田MES采集程序

This commit is contained in:
yexingqiang
2026-05-29 13:44:10 +08:00
commit c5e248e993
1399 changed files with 187196 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Specifies how JSON comments are handled when loading JSON.
/// </summary>
public enum CommentHandling
{
/// <summary>
/// Ignore comments.
/// </summary>
Ignore = 0,
/// <summary>
/// Load comments as a <see cref="JValue"/> with type <see cref="JTokenType.Comment"/>.
/// </summary>
Load = 1
}
/// <summary>
/// Specifies how line information is handled when loading JSON.
/// </summary>
public enum LineInfoHandling
{
/// <summary>
/// Ignore line information.
/// </summary>
Ignore = 0,
/// <summary>
/// Load line information.
/// </summary>
Load = 1
}
}

View File

@@ -0,0 +1,332 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Utilities;
using System.Globalization;
#if NET20
using Newtonsoft.Json.Utilities.LinqBridge;
#else
using System.Linq;
#endif
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Contains the LINQ to JSON extension methods.
/// </summary>
public static class Extensions
{
/// <summary>
/// Returns a collection of tokens that contains the ancestors of every token in the source collection.
/// </summary>
/// <typeparam name="T">The type of the objects in source, constrained to <see cref="JToken"/>.</typeparam>
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
/// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the ancestors of every token in the source collection.</returns>
public static IJEnumerable<JToken> Ancestors<T>(this IEnumerable<T> source) where T : JToken
{
ValidationUtils.ArgumentNotNull(source, nameof(source));
return source.SelectMany(j => j.Ancestors()).AsJEnumerable();
}
/// <summary>
/// Returns a collection of tokens that contains every token in the source collection, and the ancestors of every token in the source collection.
/// </summary>
/// <typeparam name="T">The type of the objects in source, constrained to <see cref="JToken"/>.</typeparam>
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
/// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains every token in the source collection, the ancestors of every token in the source collection.</returns>
public static IJEnumerable<JToken> AncestorsAndSelf<T>(this IEnumerable<T> source) where T : JToken
{
ValidationUtils.ArgumentNotNull(source, nameof(source));
return source.SelectMany(j => j.AncestorsAndSelf()).AsJEnumerable();
}
/// <summary>
/// Returns a collection of tokens that contains the descendants of every token in the source collection.
/// </summary>
/// <typeparam name="T">The type of the objects in source, constrained to <see cref="JContainer"/>.</typeparam>
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
/// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the descendants of every token in the source collection.</returns>
public static IJEnumerable<JToken> Descendants<T>(this IEnumerable<T> source) where T : JContainer
{
ValidationUtils.ArgumentNotNull(source, nameof(source));
return source.SelectMany(j => j.Descendants()).AsJEnumerable();
}
/// <summary>
/// Returns a collection of tokens that contains every token in the source collection, and the descendants of every token in the source collection.
/// </summary>
/// <typeparam name="T">The type of the objects in source, constrained to <see cref="JContainer"/>.</typeparam>
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
/// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains every token in the source collection, and the descendants of every token in the source collection.</returns>
public static IJEnumerable<JToken> DescendantsAndSelf<T>(this IEnumerable<T> source) where T : JContainer
{
ValidationUtils.ArgumentNotNull(source, nameof(source));
return source.SelectMany(j => j.DescendantsAndSelf()).AsJEnumerable();
}
/// <summary>
/// Returns a collection of child properties of every object in the source collection.
/// </summary>
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JObject"/> that contains the source collection.</param>
/// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JProperty"/> that contains the properties of every object in the source collection.</returns>
public static IJEnumerable<JProperty> Properties(this IEnumerable<JObject> source)
{
ValidationUtils.ArgumentNotNull(source, nameof(source));
return source.SelectMany(d => d.Properties()).AsJEnumerable();
}
/// <summary>
/// Returns a collection of child values of every object in the source collection with the given key.
/// </summary>
/// <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>
/// <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)
{
return Values<JToken, JToken>(source, key).AsJEnumerable();
}
/// <summary>
/// Returns a collection of child values of every object in the source collection.
/// </summary>
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
/// <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> Values(this IEnumerable<JToken> source)
{
return source.Values(null);
}
/// <summary>
/// Returns a collection of converted child values of every object in the source collection with the given key.
/// </summary>
/// <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="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>
public static IEnumerable<U> Values<U>(this IEnumerable<JToken> source, object key)
{
return Values<JToken, U>(source, key);
}
/// <summary>
/// Returns a collection of converted child values of every object in the source collection.
/// </summary>
/// <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>
/// <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)
{
return Values<JToken, U>(source, null);
}
/// <summary>
/// Converts the value.
/// </summary>
/// <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>
/// <returns>A converted value.</returns>
public static U Value<U>(this IEnumerable<JToken> value)
{
return value.Value<JToken, U>();
}
/// <summary>
/// Converts the value.
/// </summary>
/// <typeparam name="T">The source collection type.</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>
/// <returns>A converted value.</returns>
public static U Value<T, U>(this IEnumerable<T> value) where T : JToken
{
ValidationUtils.ArgumentNotNull(value, nameof(value));
JToken token = value as JToken;
if (token == null)
{
throw new ArgumentException("Source value must be a JToken.");
}
return token.Convert<JToken, U>();
}
internal static IEnumerable<U> Values<T, U>(this IEnumerable<T> source, object key) where T : JToken
{
ValidationUtils.ArgumentNotNull(source, nameof(source));
foreach (JToken token in source)
{
if (key == null)
{
if (token is JValue)
{
yield return Convert<JValue, U>((JValue)token);
}
else
{
foreach (JToken t in token.Children())
{
yield return t.Convert<JToken, U>();
}
}
}
else
{
JToken value = token[key];
if (value != null)
{
yield return value.Convert<JToken, U>();
}
}
}
yield break;
}
//TODO
//public static IEnumerable<T> InDocumentOrder<T>(this IEnumerable<T> source) where T : JObject;
/// <summary>
/// Returns a collection of child tokens of every array in the source collection.
/// </summary>
/// <typeparam name="T">The source collection type.</typeparam>
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
/// <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
{
return Children<T, JToken>(source).AsJEnumerable();
}
/// <summary>
/// Returns a collection of converted child tokens of every array in the source collection.
/// </summary>
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
/// <typeparam name="U">The type to convert the values to.</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>
public static IEnumerable<U> Children<T, U>(this IEnumerable<T> source) where T : JToken
{
ValidationUtils.ArgumentNotNull(source, nameof(source));
return source.SelectMany(c => c.Children()).Convert<JToken, U>();
}
internal static IEnumerable<U> Convert<T, U>(this IEnumerable<T> source) where T : JToken
{
ValidationUtils.ArgumentNotNull(source, nameof(source));
foreach (T token in source)
{
yield return Convert<JToken, U>(token);
}
}
internal static U Convert<T, U>(this T token) where T : JToken
{
if (token == null)
{
return default(U);
}
if (token is U
// don't want to cast JValue to its interfaces, want to get the internal value
&& typeof(U) != typeof(IComparable) && typeof(U) != typeof(IFormattable))
{
// HACK
return (U)(object)token;
}
else
{
JValue value = token as JValue;
if (value == null)
{
throw new InvalidCastException("Cannot cast {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, token.GetType(), typeof(T)));
}
if (value.Value is U)
{
return (U)value.Value;
}
Type targetType = typeof(U);
if (ReflectionUtils.IsNullableType(targetType))
{
if (value.Value == null)
{
return default(U);
}
targetType = Nullable.GetUnderlyingType(targetType);
}
return (U)System.Convert.ChangeType(value.Value, targetType, CultureInfo.InvariantCulture);
}
}
//TODO
//public static void Remove<T>(this IEnumerable<T> source) where T : JContainer;
/// <summary>
/// Returns the input typed as <see cref="IJEnumerable{T}"/>.
/// </summary>
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
/// <returns>The input typed as <see cref="IJEnumerable{T}"/>.</returns>
public static IJEnumerable<JToken> AsJEnumerable(this IEnumerable<JToken> source)
{
return source.AsJEnumerable<JToken>();
}
/// <summary>
/// Returns the input typed as <see cref="IJEnumerable{T}"/>.
/// </summary>
/// <typeparam name="T">The source collection type.</typeparam>
/// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
/// <returns>The input typed as <see cref="IJEnumerable{T}"/>.</returns>
public static IJEnumerable<T> AsJEnumerable<T>(this IEnumerable<T> source) where T : JToken
{
if (source == null)
{
return null;
}
else if (source is IJEnumerable<T>)
{
return (IJEnumerable<T>)source;
}
else
{
return new JEnumerable<T>(source);
}
}
}
}

View File

@@ -0,0 +1,46 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System.Collections.Generic;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Represents a collection of <see cref="JToken"/> objects.
/// </summary>
/// <typeparam name="T">The type of token</typeparam>
public interface IJEnumerable<
#if !(NET20 || NET35)
out
#endif
T> : IEnumerable<T> where T : JToken
{
/// <summary>
/// Gets the <see cref="IJEnumerable{JToken}"/> with the specified key.
/// </summary>
/// <value></value>
IJEnumerable<JToken> this[object key] { get; }
}
}

View File

@@ -0,0 +1,406 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json.Utilities;
using System.IO;
using System.Globalization;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Represents a JSON array.
/// </summary>
/// <example>
/// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParseArray" title="Parsing a JSON Array from Text" />
/// </example>
public class JArray : JContainer, IList<JToken>
{
private readonly List<JToken> _values = new List<JToken>();
/// <summary>
/// Gets the container's children tokens.
/// </summary>
/// <value>The container's children tokens.</value>
protected override IList<JToken> ChildrenTokens
{
get { return _values; }
}
/// <summary>
/// Gets the node type for this <see cref="JToken"/>.
/// </summary>
/// <value>The type.</value>
public override JTokenType Type
{
get { return JTokenType.Array; }
}
/// <summary>
/// Initializes a new instance of the <see cref="JArray"/> class.
/// </summary>
public JArray()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JArray"/> class from another <see cref="JArray"/> object.
/// </summary>
/// <param name="other">A <see cref="JArray"/> object to copy from.</param>
public JArray(JArray other)
: base(other)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JArray"/> class with the specified content.
/// </summary>
/// <param name="content">The contents of the array.</param>
public JArray(params object[] content)
: this((object)content)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JArray"/> class with the specified content.
/// </summary>
/// <param name="content">The contents of the array.</param>
public JArray(object content)
{
Add(content);
}
internal override bool DeepEquals(JToken node)
{
JArray t = node as JArray;
return (t != null && ContentsEqual(t));
}
internal override JToken CloneToken()
{
return new JArray(this);
}
/// <summary>
/// Loads an <see cref="JArray"/> from a <see cref="JsonReader"/>.
/// </summary>
/// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JArray"/>.</param>
/// <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)
{
return Load(reader, null);
}
/// <summary>
/// Loads an <see cref="JArray"/> from a <see cref="JsonReader"/>.
/// </summary>
/// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JArray"/>.</param>
/// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
/// If this is null, 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>
public new static JArray Load(JsonReader reader, JsonLoadSettings settings)
{
if (reader.TokenType == JsonToken.None)
{
if (!reader.Read())
{
throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader.");
}
}
reader.MoveToContent();
if (reader.TokenType != JsonToken.StartArray)
{
throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
}
JArray a = new JArray();
a.SetLineInfo(reader as IJsonLineInfo, settings);
a.ReadTokenFrom(reader, settings);
return a;
}
/// <summary>
/// Load a <see cref="JArray"/> from a string that contains JSON.
/// </summary>
/// <param name="json">A <see cref="String"/> that contains JSON.</param>
/// <returns>A <see cref="JArray"/> populated from the string that contains JSON.</returns>
/// <example>
/// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParseArray" title="Parsing a JSON Array from Text" />
/// </example>
public new static JArray Parse(string json)
{
return Parse(json, null);
}
/// <summary>
/// Load a <see cref="JArray"/> from a string that contains JSON.
/// </summary>
/// <param name="json">A <see cref="String"/> that contains JSON.</param>
/// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
/// If this is null, default load settings will be used.</param>
/// <returns>A <see cref="JArray"/> populated from the string that contains JSON.</returns>
/// <example>
/// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParseArray" title="Parsing a JSON Array from Text" />
/// </example>
public new static JArray Parse(string json, JsonLoadSettings settings)
{
using (JsonReader reader = new JsonTextReader(new StringReader(json)))
{
JArray a = Load(reader, settings);
if (reader.Read() && reader.TokenType != JsonToken.Comment)
{
throw JsonReaderException.Create(reader, "Additional text found in JSON string after parsing content.");
}
return a;
}
}
/// <summary>
/// Creates a <see cref="JArray"/> from an object.
/// </summary>
/// <param name="o">The object that will be used to create <see cref="JArray"/>.</param>
/// <returns>A <see cref="JArray"/> with the values of the specified object</returns>
public new static JArray FromObject(object o)
{
return FromObject(o, JsonSerializer.CreateDefault());
}
/// <summary>
/// Creates a <see cref="JArray"/> from an object.
/// </summary>
/// <param name="o">The object that will be used to create <see cref="JArray"/>.</param>
/// <param name="jsonSerializer">The <see cref="JsonSerializer"/> that will be used to read the object.</param>
/// <returns>A <see cref="JArray"/> with the values of the specified object</returns>
public new static JArray FromObject(object o, JsonSerializer jsonSerializer)
{
JToken token = FromObjectInternal(o, jsonSerializer);
if (token.Type != JTokenType.Array)
{
throw new ArgumentException("Object serialized to {0}. JArray instance expected.".FormatWith(CultureInfo.InvariantCulture, token.Type));
}
return (JArray)token;
}
/// <summary>
/// Writes this token to a <see cref="JsonWriter"/>.
/// </summary>
/// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</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)
{
writer.WriteStartArray();
for (int i = 0; i < _values.Count; i++)
{
_values[i].WriteTo(writer, converters);
}
writer.WriteEndArray();
}
/// <summary>
/// Gets the <see cref="JToken"/> with the specified key.
/// </summary>
/// <value>The <see cref="JToken"/> with the specified key.</value>
public override JToken this[object key]
{
get
{
ValidationUtils.ArgumentNotNull(key, nameof(key));
if (!(key is int))
{
throw new ArgumentException("Accessed JArray values with invalid key value: {0}. Int32 array index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
}
return GetItem((int)key);
}
set
{
ValidationUtils.ArgumentNotNull(key, nameof(key));
if (!(key is int))
{
throw new ArgumentException("Set JArray values with invalid key value: {0}. Int32 array index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
}
SetItem((int)key, value);
}
}
/// <summary>
/// Gets or sets the <see cref="Newtonsoft.Json.Linq.JToken"/> at the specified index.
/// </summary>
/// <value></value>
public JToken this[int index]
{
get { return GetItem(index); }
set { SetItem(index, value); }
}
internal override void MergeItem(object content, JsonMergeSettings settings)
{
IEnumerable a = (IsMultiContent(content) || content is JArray)
? (IEnumerable)content
: null;
if (a == null)
{
return;
}
MergeEnumerableContent(this, a, settings);
}
#region IList<JToken> Members
/// <summary>
/// Determines the index of a specific item in the <see cref="T:System.Collections.Generic.IList`1"/>.
/// </summary>
/// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.IList`1"/>.</param>
/// <returns>
/// The index of <paramref name="item"/> if found in the list; otherwise, -1.
/// </returns>
public int IndexOf(JToken item)
{
return IndexOfItem(item);
}
/// <summary>
/// Inserts an item to the <see cref="T:System.Collections.Generic.IList`1"/> at the specified index.
/// </summary>
/// <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
/// <param name="item">The object to insert into the <see cref="T:System.Collections.Generic.IList`1"/>.</param>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.</exception>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.</exception>
public void Insert(int index, JToken item)
{
InsertItem(index, item, false);
}
/// <summary>
/// Removes the <see cref="T:System.Collections.Generic.IList`1"/> item at the specified index.
/// </summary>
/// <param name="index">The zero-based index of the item to remove.</param>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.</exception>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.</exception>
public void RemoveAt(int index)
{
RemoveItemAt(index);
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.
/// </returns>
public IEnumerator<JToken> GetEnumerator()
{
return Children().GetEnumerator();
}
#endregion
#region ICollection<JToken> Members
/// <summary>
/// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
public void Add(JToken item)
{
Add((object)item);
}
/// <summary>
/// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
public void Clear()
{
ClearItems();
}
/// <summary>
/// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value.
/// </summary>
/// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
/// <returns>
/// true if <paramref name="item"/> is found in the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false.
/// </returns>
public bool Contains(JToken item)
{
return ContainsItem(item);
}
/// <summary>
/// Copies to.
/// </summary>
/// <param name="array">The array.</param>
/// <param name="arrayIndex">Index of the array.</param>
public void CopyTo(JToken[] array, int arrayIndex)
{
CopyItemsTo(array, arrayIndex);
}
/// <summary>
/// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.
/// </summary>
/// <returns>true if the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only; otherwise, false.</returns>
public bool IsReadOnly
{
get { return false; }
}
/// <summary>
/// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </summary>
/// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
/// <returns>
/// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
/// </returns>
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
public bool Remove(JToken item)
{
return RemoveItem(item);
}
#endregion
internal override int GetDeepHashCode()
{
return ContentsHashCode();
}
}
}

View File

@@ -0,0 +1,247 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json.Utilities;
using System.Globalization;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Represents a JSON constructor.
/// </summary>
public class JConstructor : JContainer
{
private string _name;
private readonly List<JToken> _values = new List<JToken>();
/// <summary>
/// Gets the container's children tokens.
/// </summary>
/// <value>The container's children tokens.</value>
protected override IList<JToken> ChildrenTokens
{
get { return _values; }
}
internal override void MergeItem(object content, JsonMergeSettings settings)
{
JConstructor c = content as JConstructor;
if (c == null)
{
return;
}
if (c.Name != null)
{
Name = c.Name;
}
MergeEnumerableContent(this, c, settings);
}
/// <summary>
/// Gets or sets the name of this constructor.
/// </summary>
/// <value>The constructor name.</value>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
/// Gets the node type for this <see cref="JToken"/>.
/// </summary>
/// <value>The type.</value>
public override JTokenType Type
{
get { return JTokenType.Constructor; }
}
/// <summary>
/// Initializes a new instance of the <see cref="JConstructor"/> class.
/// </summary>
public JConstructor()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JConstructor"/> class from another <see cref="JConstructor"/> object.
/// </summary>
/// <param name="other">A <see cref="JConstructor"/> object to copy from.</param>
public JConstructor(JConstructor other)
: base(other)
{
_name = other.Name;
}
/// <summary>
/// Initializes a new instance of the <see cref="JConstructor"/> class with the specified name and content.
/// </summary>
/// <param name="name">The constructor name.</param>
/// <param name="content">The contents of the constructor.</param>
public JConstructor(string name, params object[] content)
: this(name, (object)content)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JConstructor"/> class with the specified name and content.
/// </summary>
/// <param name="name">The constructor name.</param>
/// <param name="content">The contents of the constructor.</param>
public JConstructor(string name, object content)
: this(name)
{
Add(content);
}
/// <summary>
/// Initializes a new instance of the <see cref="JConstructor"/> class with the specified name.
/// </summary>
/// <param name="name">The constructor name.</param>
public JConstructor(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (name.Length == 0)
{
throw new ArgumentException("Constructor name cannot be empty.", nameof(name));
}
_name = name;
}
internal override bool DeepEquals(JToken node)
{
JConstructor c = node as JConstructor;
return (c != null && _name == c.Name && ContentsEqual(c));
}
internal override JToken CloneToken()
{
return new JConstructor(this);
}
/// <summary>
/// Writes this token to a <see cref="JsonWriter"/>.
/// </summary>
/// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</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)
{
writer.WriteStartConstructor(_name);
foreach (JToken token in Children())
{
token.WriteTo(writer, converters);
}
writer.WriteEndConstructor();
}
/// <summary>
/// Gets the <see cref="JToken"/> with the specified key.
/// </summary>
/// <value>The <see cref="JToken"/> with the specified key.</value>
public override JToken this[object key]
{
get
{
ValidationUtils.ArgumentNotNull(key, nameof(key));
if (!(key is int))
{
throw new ArgumentException("Accessed JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
}
return GetItem((int)key);
}
set
{
ValidationUtils.ArgumentNotNull(key, nameof(key));
if (!(key is int))
{
throw new ArgumentException("Set JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
}
SetItem((int)key, value);
}
}
internal override int GetDeepHashCode()
{
return _name.GetHashCode() ^ ContentsHashCode();
}
/// <summary>
/// Loads an <see cref="JConstructor"/> from a <see cref="JsonReader"/>.
/// </summary>
/// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JConstructor"/>.</param>
/// <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)
{
return Load(reader, null);
}
/// <summary>
/// Loads an <see cref="JConstructor"/> from a <see cref="JsonReader"/>.
/// </summary>
/// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JConstructor"/>.</param>
/// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
/// If this is null, 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>
public new static JConstructor Load(JsonReader reader, JsonLoadSettings settings)
{
if (reader.TokenType == JsonToken.None)
{
if (!reader.Read())
{
throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader.");
}
}
reader.MoveToContent();
if (reader.TokenType != JsonToken.StartConstructor)
{
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);
c.SetLineInfo(reader as IJsonLineInfo, settings);
c.ReadTokenFrom(reader, settings);
return c;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,151 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
#if NET20
using Newtonsoft.Json.Utilities.LinqBridge;
#else
using System.Linq;
#endif
using Newtonsoft.Json.Utilities;
using System.Collections;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Represents a collection of <see cref="JToken"/> objects.
/// </summary>
/// <typeparam name="T">The type of token</typeparam>
public struct JEnumerable<T> : IJEnumerable<T>, IEquatable<JEnumerable<T>> where T : JToken
{
/// <summary>
/// An empty collection of <see cref="JToken"/> objects.
/// </summary>
public static readonly JEnumerable<T> Empty = new JEnumerable<T>(Enumerable.Empty<T>());
private readonly IEnumerable<T> _enumerable;
/// <summary>
/// Initializes a new instance of the <see cref="JEnumerable{T}"/> struct.
/// </summary>
/// <param name="enumerable">The enumerable.</param>
public JEnumerable(IEnumerable<T> enumerable)
{
ValidationUtils.ArgumentNotNull(enumerable, nameof(enumerable));
_enumerable = enumerable;
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
public IEnumerator<T> GetEnumerator()
{
if (_enumerable == null)
{
return Empty.GetEnumerator();
}
return _enumerable.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Gets the <see cref="IJEnumerable{JToken}"/> with the specified key.
/// </summary>
/// <value></value>
public IJEnumerable<JToken> this[object key]
{
get
{
if (_enumerable == null)
{
return JEnumerable<JToken>.Empty;
}
return new JEnumerable<JToken>(_enumerable.Values<T, JToken>(key));
}
}
/// <summary>
/// Determines whether the specified <see cref="JEnumerable{T}"/> is equal to this instance.
/// </summary>
/// <param name="other">The <see cref="JEnumerable{T}"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="JEnumerable{T}"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public bool Equals(JEnumerable<T> other)
{
return Equals(_enumerable, other._enumerable);
}
/// <summary>
/// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
/// </summary>
/// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj)
{
if (obj is JEnumerable<T>)
{
return Equals((JEnumerable<T>)obj);
}
return false;
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
if (_enumerable == null)
{
return 0;
}
return _enumerable.GetHashCode();
}
}
}

View File

@@ -0,0 +1,905 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
#if !PORTABLE40
using System.Collections.Specialized;
#endif
using System.ComponentModel;
#if !(NET35 || NET20 || PORTABLE40)
using System.Dynamic;
using System.Linq.Expressions;
#endif
using System.IO;
using Newtonsoft.Json.Utilities;
using System.Globalization;
#if NET20
using Newtonsoft.Json.Utilities.LinqBridge;
#else
using System.Linq;
#endif
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Represents a JSON object.
/// </summary>
/// <example>
/// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParse" title="Parsing a JSON Object from Text" />
/// </example>
public class JObject : JContainer, IDictionary<string, JToken>, INotifyPropertyChanged
#if !(DOTNET || PORTABLE40 || PORTABLE)
, ICustomTypeDescriptor
#endif
#if !(NET20 || PORTABLE40 || PORTABLE)
, INotifyPropertyChanging
#endif
{
private readonly JPropertyKeyedCollection _properties = new JPropertyKeyedCollection();
/// <summary>
/// Gets the container's children tokens.
/// </summary>
/// <value>The container's children tokens.</value>
protected override IList<JToken> ChildrenTokens
{
get { return _properties; }
}
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#if !(NET20 || PORTABLE || PORTABLE40)
/// <summary>
/// Occurs when a property value is changing.
/// </summary>
public event PropertyChangingEventHandler PropertyChanging;
#endif
/// <summary>
/// Initializes a new instance of the <see cref="JObject"/> class.
/// </summary>
public JObject()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JObject"/> class from another <see cref="JObject"/> object.
/// </summary>
/// <param name="other">A <see cref="JObject"/> object to copy from.</param>
public JObject(JObject other)
: base(other)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JObject"/> class with the specified content.
/// </summary>
/// <param name="content">The contents of the object.</param>
public JObject(params object[] content)
: this((object)content)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JObject"/> class with the specified content.
/// </summary>
/// <param name="content">The contents of the object.</param>
public JObject(object content)
{
Add(content);
}
internal override bool DeepEquals(JToken node)
{
JObject t = node as JObject;
if (t == null)
{
return false;
}
return _properties.Compare(t._properties);
}
internal override void InsertItem(int index, JToken item, bool skipParentCheck)
{
// don't add comments to JObject, no name to reference comment by
if (item != null && item.Type == JTokenType.Comment)
{
return;
}
base.InsertItem(index, item, skipParentCheck);
}
internal override void ValidateToken(JToken o, JToken existing)
{
ValidationUtils.ArgumentNotNull(o, nameof(o));
if (o.Type != JTokenType.Property)
{
throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType()));
}
JProperty newProperty = (JProperty)o;
if (existing != null)
{
JProperty existingProperty = (JProperty)existing;
if (newProperty.Name == existingProperty.Name)
{
return;
}
}
if (_properties.TryGetValue(newProperty.Name, out existing))
{
throw new ArgumentException("Can not add property {0} to {1}. Property with the same name already exists on object.".FormatWith(CultureInfo.InvariantCulture, newProperty.Name, GetType()));
}
}
internal override void MergeItem(object content, JsonMergeSettings settings)
{
JObject o = content as JObject;
if (o == null)
{
return;
}
foreach (KeyValuePair<string, JToken> contentItem in o)
{
JProperty existingProperty = Property(contentItem.Key);
if (existingProperty == null)
{
Add(contentItem.Key, contentItem.Value);
}
else if (contentItem.Value != null)
{
JContainer existingContainer = existingProperty.Value as JContainer;
if (existingContainer == null)
{
if (contentItem.Value.Type != JTokenType.Null || settings?.MergeNullValueHandling == MergeNullValueHandling.Merge)
{
existingProperty.Value = contentItem.Value;
}
}
else if (existingContainer.Type != contentItem.Value.Type)
{
existingProperty.Value = contentItem.Value;
}
else
{
existingContainer.Merge(contentItem.Value, settings);
}
}
}
}
internal void InternalPropertyChanged(JProperty childProperty)
{
OnPropertyChanged(childProperty.Name);
#if !(DOTNET || PORTABLE40 || PORTABLE)
if (_listChanged != null)
{
OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, IndexOfItem(childProperty)));
}
#endif
#if !(NET20 || NET35 || PORTABLE40)
if (_collectionChanged != null)
{
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, childProperty, childProperty, IndexOfItem(childProperty)));
}
#endif
}
internal void InternalPropertyChanging(JProperty childProperty)
{
#if !(NET20 || PORTABLE40 || PORTABLE)
OnPropertyChanging(childProperty.Name);
#endif
}
internal override JToken CloneToken()
{
return new JObject(this);
}
/// <summary>
/// Gets the node type for this <see cref="JToken"/>.
/// </summary>
/// <value>The type.</value>
public override JTokenType Type
{
get { return JTokenType.Object; }
}
/// <summary>
/// Gets an <see cref="IEnumerable{JProperty}"/> of this object's properties.
/// </summary>
/// <returns>An <see cref="IEnumerable{JProperty}"/> of this object's properties.</returns>
public IEnumerable<JProperty> Properties()
{
return _properties.Cast<JProperty>();
}
/// <summary>
/// Gets a <see cref="JProperty"/> the specified name.
/// </summary>
/// <param name="name">The property name.</param>
/// <returns>A <see cref="JProperty"/> with the specified name or null.</returns>
public JProperty Property(string name)
{
if (name == null)
{
return null;
}
JToken property;
_properties.TryGetValue(name, out property);
return (JProperty)property;
}
/// <summary>
/// Gets an <see cref="JEnumerable{JToken}"/> of this object's property values.
/// </summary>
/// <returns>An <see cref="JEnumerable{JToken}"/> of this object's property values.</returns>
public JEnumerable<JToken> PropertyValues()
{
return new JEnumerable<JToken>(Properties().Select(p => p.Value));
}
/// <summary>
/// Gets the <see cref="JToken"/> with the specified key.
/// </summary>
/// <value>The <see cref="JToken"/> with the specified key.</value>
public override JToken this[object key]
{
get
{
ValidationUtils.ArgumentNotNull(key, nameof(key));
string propertyName = key as string;
if (propertyName == null)
{
throw new ArgumentException("Accessed JObject values with invalid key value: {0}. Object property name expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
}
return this[propertyName];
}
set
{
ValidationUtils.ArgumentNotNull(key, nameof(key));
string propertyName = key as string;
if (propertyName == null)
{
throw new ArgumentException("Set JObject values with invalid key value: {0}. Object property name expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
}
this[propertyName] = value;
}
}
/// <summary>
/// Gets or sets the <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.
/// </summary>
/// <value></value>
public JToken this[string propertyName]
{
get
{
ValidationUtils.ArgumentNotNull(propertyName, nameof(propertyName));
JProperty property = Property(propertyName);
return (property != null) ? property.Value : null;
}
set
{
JProperty property = Property(propertyName);
if (property != null)
{
property.Value = value;
}
else
{
#if !(NET20 || PORTABLE40 || PORTABLE)
OnPropertyChanging(propertyName);
#endif
Add(new JProperty(propertyName, value));
OnPropertyChanged(propertyName);
}
}
}
/// <summary>
/// Loads an <see cref="JObject"/> from a <see cref="JsonReader"/>.
/// </summary>
/// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JObject"/>.</param>
/// <returns>A <see cref="JObject"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
public new static JObject Load(JsonReader reader)
{
return Load(reader, null);
}
/// <summary>
/// Loads an <see cref="JObject"/> from a <see cref="JsonReader"/>.
/// </summary>
/// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JObject"/>.</param>
/// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
/// If this is null, default load settings will be used.</param>
/// <returns>A <see cref="JObject"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
public new static JObject Load(JsonReader reader, JsonLoadSettings settings)
{
ValidationUtils.ArgumentNotNull(reader, nameof(reader));
if (reader.TokenType == JsonToken.None)
{
if (!reader.Read())
{
throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader.");
}
}
reader.MoveToContent();
if (reader.TokenType != JsonToken.StartObject)
{
throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
}
JObject o = new JObject();
o.SetLineInfo(reader as IJsonLineInfo, settings);
o.ReadTokenFrom(reader, settings);
return o;
}
/// <summary>
/// Load a <see cref="JObject"/> from a string that contains JSON.
/// </summary>
/// <param name="json">A <see cref="String"/> that contains JSON.</param>
/// <returns>A <see cref="JObject"/> populated from the string that contains JSON.</returns>
/// <example>
/// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParse" title="Parsing a JSON Object from Text" />
/// </example>
public new static JObject Parse(string json)
{
return Parse(json, null);
}
/// <summary>
/// Load a <see cref="JObject"/> from a string that contains JSON.
/// </summary>
/// <param name="json">A <see cref="String"/> that contains JSON.</param>
/// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
/// If this is null, default load settings will be used.</param>
/// <returns>A <see cref="JObject"/> populated from the string that contains JSON.</returns>
/// <example>
/// <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParse" title="Parsing a JSON Object from Text" />
/// </example>
public new static JObject Parse(string json, JsonLoadSettings settings)
{
using (JsonReader reader = new JsonTextReader(new StringReader(json)))
{
JObject o = Load(reader, settings);
if (reader.Read() && reader.TokenType != JsonToken.Comment)
{
throw JsonReaderException.Create(reader, "Additional text found in JSON string after parsing content.");
}
return o;
}
}
/// <summary>
/// Creates a <see cref="JObject"/> from an object.
/// </summary>
/// <param name="o">The object that will be used to create <see cref="JObject"/>.</param>
/// <returns>A <see cref="JObject"/> with the values of the specified object</returns>
public new static JObject FromObject(object o)
{
return FromObject(o, JsonSerializer.CreateDefault());
}
/// <summary>
/// Creates a <see cref="JObject"/> from an object.
/// </summary>
/// <param name="o">The object that will be used to create <see cref="JObject"/>.</param>
/// <param name="jsonSerializer">The <see cref="JsonSerializer"/> that will be used to read the object.</param>
/// <returns>A <see cref="JObject"/> with the values of the specified object</returns>
public new static JObject FromObject(object o, JsonSerializer jsonSerializer)
{
JToken token = FromObjectInternal(o, jsonSerializer);
if (token != null && token.Type != JTokenType.Object)
{
throw new ArgumentException("Object serialized to {0}. JObject instance expected.".FormatWith(CultureInfo.InvariantCulture, token.Type));
}
return (JObject)token;
}
/// <summary>
/// Writes this token to a <see cref="JsonWriter"/>.
/// </summary>
/// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</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)
{
writer.WriteStartObject();
for (int i = 0; i < _properties.Count; i++)
{
_properties[i].WriteTo(writer, converters);
}
writer.WriteEndObject();
}
/// <summary>
/// Gets the <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
/// <returns>The <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.</returns>
public JToken GetValue(string propertyName)
{
return GetValue(propertyName, StringComparison.Ordinal);
}
/// <summary>
/// Gets the <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.
/// The exact property name will be searched for first and if no matching property is found then
/// the <see cref="StringComparison"/> will be used to match a property.
/// </summary>
/// <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>
/// <returns>The <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.</returns>
public JToken GetValue(string propertyName, StringComparison comparison)
{
if (propertyName == null)
{
return null;
}
// attempt to get value via dictionary first for performance
JProperty property = Property(propertyName);
if (property != null)
{
return property.Value;
}
// test above already uses this comparison so no need to repeat
if (comparison != StringComparison.Ordinal)
{
foreach (JProperty p in _properties)
{
if (string.Equals(p.Name, propertyName, comparison))
{
return p.Value;
}
}
}
return null;
}
/// <summary>
/// Tries to get the <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.
/// The exact property name will be searched for first and if no matching property is found then
/// the <see cref="StringComparison"/> will be used to match a property.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
/// <param name="value">The value.</param>
/// <param name="comparison">One of the enumeration values that specifies how the strings will be compared.</param>
/// <returns>true if a value was successfully retrieved; otherwise, false.</returns>
public bool TryGetValue(string propertyName, StringComparison comparison, out JToken value)
{
value = GetValue(propertyName, comparison);
return (value != null);
}
#region IDictionary<string,JToken> Members
/// <summary>
/// Adds the specified property name.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
/// <param name="value">The value.</param>
public void Add(string propertyName, JToken value)
{
Add(new JProperty(propertyName, value));
}
bool IDictionary<string, JToken>.ContainsKey(string key)
{
return _properties.Contains(key);
}
ICollection<string> IDictionary<string, JToken>.Keys
{
// todo: make order the collection returned match JObject order
get { return _properties.Keys; }
}
/// <summary>
/// Removes the property with the specified name.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
/// <returns>true if item was successfully removed; otherwise, false.</returns>
public bool Remove(string propertyName)
{
JProperty property = Property(propertyName);
if (property == null)
{
return false;
}
property.Remove();
return true;
}
/// <summary>
/// Tries the get value.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
/// <param name="value">The value.</param>
/// <returns>true if a value was successfully retrieved; otherwise, false.</returns>
public bool TryGetValue(string propertyName, out JToken value)
{
JProperty property = Property(propertyName);
if (property == null)
{
value = null;
return false;
}
value = property.Value;
return true;
}
ICollection<JToken> IDictionary<string, JToken>.Values
{
get
{
// todo: need to wrap _properties.Values with a collection to get the JProperty value
throw new NotImplementedException();
}
}
#endregion
#region ICollection<KeyValuePair<string,JToken>> Members
void ICollection<KeyValuePair<string, JToken>>.Add(KeyValuePair<string, JToken> item)
{
Add(new JProperty(item.Key, item.Value));
}
void ICollection<KeyValuePair<string, JToken>>.Clear()
{
RemoveAll();
}
bool ICollection<KeyValuePair<string, JToken>>.Contains(KeyValuePair<string, JToken> item)
{
JProperty property = Property(item.Key);
if (property == null)
{
return false;
}
return (property.Value == item.Value);
}
void ICollection<KeyValuePair<string, JToken>>.CopyTo(KeyValuePair<string, JToken>[] array, int arrayIndex)
{
if (array == null)
{
throw new ArgumentNullException(nameof(array));
}
if (arrayIndex < 0)
{
throw new ArgumentOutOfRangeException(nameof(arrayIndex), "arrayIndex is less than 0.");
}
if (arrayIndex >= array.Length && arrayIndex != 0)
{
throw new ArgumentException("arrayIndex is equal to or greater than the length of array.");
}
if (Count > array.Length - arrayIndex)
{
throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array.");
}
int index = 0;
foreach (JProperty property in _properties)
{
array[arrayIndex + index] = new KeyValuePair<string, JToken>(property.Name, property.Value);
index++;
}
}
bool ICollection<KeyValuePair<string, JToken>>.IsReadOnly
{
get { return false; }
}
bool ICollection<KeyValuePair<string, JToken>>.Remove(KeyValuePair<string, JToken> item)
{
if (!((ICollection<KeyValuePair<string, JToken>>)this).Contains(item))
{
return false;
}
((IDictionary<string, JToken>)this).Remove(item.Key);
return true;
}
#endregion
internal override int GetDeepHashCode()
{
return ContentsHashCode();
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
/// </returns>
public IEnumerator<KeyValuePair<string, JToken>> GetEnumerator()
{
foreach (JProperty property in _properties)
{
yield return new KeyValuePair<string, JToken>(property.Name, property.Value);
}
}
/// <summary>
/// Raises the <see cref="PropertyChanged"/> event with the provided arguments.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#if !(PORTABLE40 || PORTABLE || NET20)
/// <summary>
/// Raises the <see cref="PropertyChanging"/> event with the provided arguments.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
protected virtual void OnPropertyChanging(string propertyName)
{
if (PropertyChanging != null)
{
PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
}
}
#endif
#if !(DOTNET || PORTABLE40 || PORTABLE)
// include custom type descriptor on JObject rather than use a provider because the properties are specific to a type
#region ICustomTypeDescriptor
/// <summary>
/// Returns the properties for this instance of a component.
/// </summary>
/// <returns>
/// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> that represents the properties for this component instance.
/// </returns>
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
{
return ((ICustomTypeDescriptor)this).GetProperties(null);
}
/// <summary>
/// Returns the properties for this instance of a component using the attribute array as a filter.
/// </summary>
/// <param name="attributes">An array of type <see cref="T:System.Attribute"/> that is used as a filter.</param>
/// <returns>
/// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> that represents the filtered properties for this component instance.
/// </returns>
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{
PropertyDescriptorCollection descriptors = new PropertyDescriptorCollection(null);
foreach (KeyValuePair<string, JToken> propertyValue in this)
{
descriptors.Add(new JPropertyDescriptor(propertyValue.Key));
}
return descriptors;
}
/// <summary>
/// Returns a collection of custom attributes for this instance of a component.
/// </summary>
/// <returns>
/// An <see cref="T:System.ComponentModel.AttributeCollection"/> containing the attributes for this object.
/// </returns>
AttributeCollection ICustomTypeDescriptor.GetAttributes()
{
return AttributeCollection.Empty;
}
/// <summary>
/// Returns the class name of this instance of a component.
/// </summary>
/// <returns>
/// The class name of the object, or null if the class does not have a name.
/// </returns>
string ICustomTypeDescriptor.GetClassName()
{
return null;
}
/// <summary>
/// Returns the name of this instance of a component.
/// </summary>
/// <returns>
/// The name of the object, or null if the object does not have a name.
/// </returns>
string ICustomTypeDescriptor.GetComponentName()
{
return null;
}
/// <summary>
/// Returns a type converter for this instance of a component.
/// </summary>
/// <returns>
/// A <see cref="T:System.ComponentModel.TypeConverter"/> that is the converter for this object, or null if there is no <see cref="T:System.ComponentModel.TypeConverter"/> for this object.
/// </returns>
TypeConverter ICustomTypeDescriptor.GetConverter()
{
return new TypeConverter();
}
/// <summary>
/// Returns the default event for this instance of a component.
/// </summary>
/// <returns>
/// An <see cref="T:System.ComponentModel.EventDescriptor"/> that represents the default event for this object, or null if this object does not have events.
/// </returns>
EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
{
return null;
}
/// <summary>
/// Returns the default property for this instance of a component.
/// </summary>
/// <returns>
/// A <see cref="T:System.ComponentModel.PropertyDescriptor"/> that represents the default property for this object, or null if this object does not have properties.
/// </returns>
PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
{
return null;
}
/// <summary>
/// Returns an editor of the specified type for this instance of a component.
/// </summary>
/// <param name="editorBaseType">A <see cref="T:System.Type"/> that represents the editor for this object.</param>
/// <returns>
/// An <see cref="T:System.Object"/> of the specified type that is the editor for this object, or null if the editor cannot be found.
/// </returns>
object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
{
return null;
}
/// <summary>
/// Returns the events for this instance of a component using the specified attribute array as a filter.
/// </summary>
/// <param name="attributes">An array of type <see cref="T:System.Attribute"/> that is used as a filter.</param>
/// <returns>
/// An <see cref="T:System.ComponentModel.EventDescriptorCollection"/> that represents the filtered events for this component instance.
/// </returns>
EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
{
return EventDescriptorCollection.Empty;
}
/// <summary>
/// Returns the events for this instance of a component.
/// </summary>
/// <returns>
/// An <see cref="T:System.ComponentModel.EventDescriptorCollection"/> that represents the events for this component instance.
/// </returns>
EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
{
return EventDescriptorCollection.Empty;
}
/// <summary>
/// Returns an object that contains the property described by the specified property descriptor.
/// </summary>
/// <param name="pd">A <see cref="T:System.ComponentModel.PropertyDescriptor"/> that represents the property whose owner is to be found.</param>
/// <returns>
/// An <see cref="T:System.Object"/> that represents the owner of the specified property.
/// </returns>
object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
{
return null;
}
#endregion
#endif
#if !(NET35 || NET20 || PORTABLE40)
/// <summary>
/// Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
/// </summary>
/// <param name="parameter">The expression tree representation of the runtime value.</param>
/// <returns>
/// The <see cref="T:System.Dynamic.DynamicMetaObject"/> to bind this object.
/// </returns>
protected override DynamicMetaObject GetMetaObject(Expression parameter)
{
return new DynamicProxyMetaObject<JObject>(parameter, this, new JObjectDynamicProxy(), true);
}
private class JObjectDynamicProxy : DynamicProxy<JObject>
{
public override bool TryGetMember(JObject instance, GetMemberBinder binder, out object result)
{
// result can be null
result = instance[binder.Name];
return true;
}
public override bool TrySetMember(JObject instance, SetMemberBinder binder, object value)
{
JToken v = value as JToken;
// this can throw an error if value isn't a valid for a JValue
if (v == null)
{
v = new JValue(value);
}
instance[binder.Name] = v;
return true;
}
public override IEnumerable<string> GetDynamicMemberNames(JObject instance)
{
return instance.Properties().Select(p => p.Name);
}
}
#endif
}
}

View File

@@ -0,0 +1,400 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json.Utilities;
using System.Diagnostics;
using System.Globalization;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Represents a JSON property.
/// </summary>
public class JProperty : JContainer
{
#region JPropertyList
private class JPropertyList : IList<JToken>
{
internal JToken _token;
public IEnumerator<JToken> GetEnumerator()
{
if (_token != null)
{
yield return _token;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(JToken item)
{
_token = item;
}
public void Clear()
{
_token = null;
}
public bool Contains(JToken item)
{
return (_token == item);
}
public void CopyTo(JToken[] array, int arrayIndex)
{
if (_token != null)
{
array[arrayIndex] = _token;
}
}
public bool Remove(JToken item)
{
if (_token == item)
{
_token = null;
return true;
}
return false;
}
public int Count
{
get { return (_token != null) ? 1 : 0; }
}
public bool IsReadOnly
{
get { return false; }
}
public int IndexOf(JToken item)
{
return (_token == item) ? 0 : -1;
}
public void Insert(int index, JToken item)
{
if (index == 0)
{
_token = item;
}
}
public void RemoveAt(int index)
{
if (index == 0)
{
_token = null;
}
}
public JToken this[int index]
{
get { return (index == 0) ? _token : null; }
set
{
if (index == 0)
{
_token = value;
}
}
}
}
#endregion
private readonly JPropertyList _content = new JPropertyList();
private readonly string _name;
/// <summary>
/// Gets the container's children tokens.
/// </summary>
/// <value>The container's children tokens.</value>
protected override IList<JToken> ChildrenTokens
{
get { return _content; }
}
/// <summary>
/// Gets the property name.
/// </summary>
/// <value>The property name.</value>
public string Name
{
[DebuggerStepThrough]
get { return _name; }
}
/// <summary>
/// Gets or sets the property value.
/// </summary>
/// <value>The property value.</value>
public JToken Value
{
[DebuggerStepThrough]
get { return _content._token; }
set
{
CheckReentrancy();
JToken newValue = value ?? JValue.CreateNull();
if (_content._token == null)
{
InsertItem(0, newValue, false);
}
else
{
SetItem(0, newValue);
}
}
}
/// <summary>
/// Initializes a new instance of the <see cref="JProperty"/> class from another <see cref="JProperty"/> object.
/// </summary>
/// <param name="other">A <see cref="JProperty"/> object to copy from.</param>
public JProperty(JProperty other)
: base(other)
{
_name = other.Name;
}
internal override JToken GetItem(int index)
{
if (index != 0)
{
throw new ArgumentOutOfRangeException();
}
return Value;
}
internal override void SetItem(int index, JToken item)
{
if (index != 0)
{
throw new ArgumentOutOfRangeException();
}
if (IsTokenUnchanged(Value, item))
{
return;
}
if (Parent != null)
{
((JObject)Parent).InternalPropertyChanging(this);
}
base.SetItem(0, item);
if (Parent != null)
{
((JObject)Parent).InternalPropertyChanged(this);
}
}
internal override bool RemoveItem(JToken item)
{
throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
}
internal override void RemoveItemAt(int index)
{
throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
}
internal override void InsertItem(int index, JToken item, bool skipParentCheck)
{
// don't add comments to JProperty
if (item != null && item.Type == JTokenType.Comment)
{
return;
}
if (Value != null)
{
throw new JsonException("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
}
base.InsertItem(0, item, false);
}
internal override bool ContainsItem(JToken item)
{
return (Value == item);
}
internal override void MergeItem(object content, JsonMergeSettings settings)
{
JProperty p = content as JProperty;
if (p == null)
{
return;
}
if (p.Value != null && p.Value.Type != JTokenType.Null)
{
Value = p.Value;
}
}
internal override void ClearItems()
{
throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
}
internal override bool DeepEquals(JToken node)
{
JProperty t = node as JProperty;
return (t != null && _name == t.Name && ContentsEqual(t));
}
internal override JToken CloneToken()
{
return new JProperty(this);
}
/// <summary>
/// Gets the node type for this <see cref="JToken"/>.
/// </summary>
/// <value>The type.</value>
public override JTokenType Type
{
[DebuggerStepThrough]
get { return JTokenType.Property; }
}
internal JProperty(string name)
{
// called from JTokenWriter
ValidationUtils.ArgumentNotNull(name, nameof(name));
_name = name;
}
/// <summary>
/// Initializes a new instance of the <see cref="JProperty"/> class.
/// </summary>
/// <param name="name">The property name.</param>
/// <param name="content">The property content.</param>
public JProperty(string name, params object[] content)
: this(name, (object)content)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JProperty"/> class.
/// </summary>
/// <param name="name">The property name.</param>
/// <param name="content">The property content.</param>
public JProperty(string name, object content)
{
ValidationUtils.ArgumentNotNull(name, nameof(name));
_name = name;
Value = IsMultiContent(content)
? new JArray(content)
: CreateFromContent(content);
}
/// <summary>
/// Writes this token to a <see cref="JsonWriter"/>.
/// </summary>
/// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</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)
{
writer.WritePropertyName(_name);
JToken value = Value;
if (value != null)
{
value.WriteTo(writer, converters);
}
else
{
writer.WriteNull();
}
}
internal override int GetDeepHashCode()
{
return _name.GetHashCode() ^ ((Value != null) ? Value.GetDeepHashCode() : 0);
}
/// <summary>
/// Loads an <see cref="JProperty"/> from a <see cref="JsonReader"/>.
/// </summary>
/// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JProperty"/>.</param>
/// <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)
{
return Load(reader, null);
}
/// <summary>
/// Loads an <see cref="JProperty"/> from a <see cref="JsonReader"/>.
/// </summary>
/// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JProperty"/>.</param>
/// <param name="settings">The <see cref="JsonLoadSettings"/> used to load the JSON.
/// If this is null, 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>
public new static JProperty Load(JsonReader reader, JsonLoadSettings settings)
{
if (reader.TokenType == JsonToken.None)
{
if (!reader.Read())
{
throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader.");
}
}
reader.MoveToContent();
if (reader.TokenType != JsonToken.PropertyName)
{
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);
p.SetLineInfo(reader as IJsonLineInfo, settings);
p.ReadTokenFrom(reader, settings);
return p;
}
}
}

View File

@@ -0,0 +1,166 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
#if !(DOTNET || PORTABLE || PORTABLE40)
using System;
using System.ComponentModel;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Represents a view of a <see cref="JProperty"/>.
/// </summary>
public class JPropertyDescriptor : PropertyDescriptor
{
/// <summary>
/// Initializes a new instance of the <see cref="JPropertyDescriptor"/> class.
/// </summary>
/// <param name="name">The name.</param>
public JPropertyDescriptor(string name)
: base(name, null)
{
}
private static JObject CastInstance(object instance)
{
return (JObject)instance;
}
/// <summary>
/// When overridden in a derived class, returns whether resetting an object changes its value.
/// </summary>
/// <returns>
/// true if resetting the component changes its value; otherwise, false.
/// </returns>
/// <param name="component">The component to test for reset capability.
/// </param>
public override bool CanResetValue(object component)
{
return false;
}
/// <summary>
/// When overridden in a derived class, gets the current value of the property on a component.
/// </summary>
/// <returns>
/// The value of a property for a given component.
/// </returns>
/// <param name="component">The component with the property for which to retrieve the value.
/// </param>
public override object GetValue(object component)
{
JToken token = CastInstance(component)[Name];
return token;
}
/// <summary>
/// When overridden in a derived class, resets the value for this property of the component to the default value.
/// </summary>
/// <param name="component">The component with the property value that is to be reset to the default value.
/// </param>
public override void ResetValue(object component)
{
}
/// <summary>
/// When overridden in a derived class, sets the value of the component to a different value.
/// </summary>
/// <param name="component">The component with the property value that is to be set.
/// </param><param name="value">The new value.
/// </param>
public override void SetValue(object component, object value)
{
JToken token = (value is JToken) ? (JToken)value : new JValue(value);
CastInstance(component)[Name] = token;
}
/// <summary>
/// When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted.
/// </summary>
/// <returns>
/// true if the property should be persisted; otherwise, false.
/// </returns>
/// <param name="component">The component with the property to be examined for persistence.
/// </param>
public override bool ShouldSerializeValue(object component)
{
return false;
}
/// <summary>
/// When overridden in a derived class, gets the type of the component this property is bound to.
/// </summary>
/// <returns>
/// A <see cref="T:System.Type"/> that represents the type of component this property is bound to. When the <see cref="M:System.ComponentModel.PropertyDescriptor.GetValue(System.Object)"/> or <see cref="M:System.ComponentModel.PropertyDescriptor.SetValue(System.Object,System.Object)"/> methods are invoked, the object specified might be an instance of this type.
/// </returns>
public override Type ComponentType
{
get { return typeof(JObject); }
}
/// <summary>
/// When overridden in a derived class, gets a value indicating whether this property is read-only.
/// </summary>
/// <returns>
/// true if the property is read-only; otherwise, false.
/// </returns>
public override bool IsReadOnly
{
get { return false; }
}
/// <summary>
/// When overridden in a derived class, gets the type of the property.
/// </summary>
/// <returns>
/// A <see cref="T:System.Type"/> that represents the type of the property.
/// </returns>
public override Type PropertyType
{
get { return typeof(object); }
}
/// <summary>
/// Gets the hash code for the name of the member.
/// </summary>
/// <value></value>
/// <returns>
/// The hash code for the name of the member.
/// </returns>
protected override int NameHashCode
{
get
{
// override property to fix up an error in its documentation
int nameHashCode = base.NameHashCode;
return nameHashCode;
}
}
}
}
#endif

View File

@@ -0,0 +1,280 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace Newtonsoft.Json.Linq
{
internal class JPropertyKeyedCollection : Collection<JToken>
{
private static readonly IEqualityComparer<string> Comparer = StringComparer.Ordinal;
private Dictionary<string, JToken> _dictionary;
private void AddKey(string key, JToken item)
{
EnsureDictionary();
_dictionary[key] = item;
}
protected void ChangeItemKey(JToken item, string newKey)
{
if (!ContainsItem(item))
{
throw new ArgumentException("The specified item does not exist in this KeyedCollection.");
}
string keyForItem = GetKeyForItem(item);
if (!Comparer.Equals(keyForItem, newKey))
{
if (newKey != null)
{
AddKey(newKey, item);
}
if (keyForItem != null)
{
RemoveKey(keyForItem);
}
}
}
protected override void ClearItems()
{
base.ClearItems();
if (_dictionary != null)
{
_dictionary.Clear();
}
}
public bool Contains(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (_dictionary != null)
{
return _dictionary.ContainsKey(key);
}
return false;
}
private bool ContainsItem(JToken item)
{
if (_dictionary == null)
{
return false;
}
string key = GetKeyForItem(item);
JToken value;
return _dictionary.TryGetValue(key, out value);
}
private void EnsureDictionary()
{
if (_dictionary == null)
{
_dictionary = new Dictionary<string, JToken>(Comparer);
}
}
private string GetKeyForItem(JToken item)
{
return ((JProperty)item).Name;
}
protected override void InsertItem(int index, JToken item)
{
AddKey(GetKeyForItem(item), item);
base.InsertItem(index, item);
}
public bool Remove(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (_dictionary != null)
{
return _dictionary.ContainsKey(key) && Remove(_dictionary[key]);
}
return false;
}
protected override void RemoveItem(int index)
{
string keyForItem = GetKeyForItem(Items[index]);
RemoveKey(keyForItem);
base.RemoveItem(index);
}
private void RemoveKey(string key)
{
if (_dictionary != null)
{
_dictionary.Remove(key);
}
}
protected override void SetItem(int index, JToken item)
{
string keyForItem = GetKeyForItem(item);
string keyAtIndex = GetKeyForItem(Items[index]);
if (Comparer.Equals(keyAtIndex, keyForItem))
{
if (_dictionary != null)
{
_dictionary[keyForItem] = item;
}
}
else
{
AddKey(keyForItem, item);
if (keyAtIndex != null)
{
RemoveKey(keyAtIndex);
}
}
base.SetItem(index, item);
}
public JToken this[string key]
{
get
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (_dictionary != null)
{
return _dictionary[key];
}
throw new KeyNotFoundException();
}
}
public bool TryGetValue(string key, out JToken value)
{
if (_dictionary == null)
{
value = null;
return false;
}
return _dictionary.TryGetValue(key, out value);
}
public ICollection<string> Keys
{
get
{
EnsureDictionary();
return _dictionary.Keys;
}
}
public ICollection<JToken> Values
{
get
{
EnsureDictionary();
return _dictionary.Values;
}
}
public bool Compare(JPropertyKeyedCollection other)
{
if (this == other)
{
return true;
}
// dictionaries in JavaScript aren't ordered
// ignore order when comparing properties
Dictionary<string, JToken> d1 = _dictionary;
Dictionary<string, JToken> d2 = other._dictionary;
if (d1 == null && d2 == null)
{
return true;
}
if (d1 == null)
{
return (d2.Count == 0);
}
if (d2 == null)
{
return (d1.Count == 0);
}
if (d1.Count != d2.Count)
{
return false;
}
foreach (KeyValuePair<string, JToken> keyAndProperty in d1)
{
JToken secondValue;
if (!d2.TryGetValue(keyAndProperty.Key, out secondValue))
{
return false;
}
JProperty p1 = (JProperty)keyAndProperty.Value;
JProperty p2 = (JProperty)secondValue;
if (p1.Value == null)
{
return (p2.Value == null);
}
if (!p1.Value.DeepEquals(p2.Value))
{
return false;
}
}
return true;
}
}
}

View File

@@ -0,0 +1,75 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System.Globalization;
using System.IO;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Represents a raw JSON string.
/// </summary>
public class JRaw : JValue
{
/// <summary>
/// Initializes a new instance of the <see cref="JRaw"/> class from another <see cref="JRaw"/> object.
/// </summary>
/// <param name="other">A <see cref="JRaw"/> object to copy from.</param>
public JRaw(JRaw other)
: base(other)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JRaw"/> class.
/// </summary>
/// <param name="rawJson">The raw json.</param>
public JRaw(object rawJson)
: base(rawJson, JTokenType.Raw)
{
}
/// <summary>
/// Creates an instance of <see cref="JRaw"/> with the content of the reader's current token.
/// </summary>
/// <param name="reader">The reader.</param>
/// <returns>An instance of <see cref="JRaw"/> with the content of the reader's current token.</returns>
public static JRaw Create(JsonReader reader)
{
using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture))
using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
{
jsonWriter.WriteToken(reader);
return new JRaw(sw.ToString());
}
}
internal override JToken CloneToken()
{
return new JRaw(this);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,64 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System.Collections.Generic;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Compares tokens to determine whether they are equal.
/// </summary>
public class JTokenEqualityComparer : IEqualityComparer<JToken>
{
/// <summary>
/// Determines whether the specified objects are equal.
/// </summary>
/// <param name="x">The first object of type <see cref="JToken"/> to compare.</param>
/// <param name="y">The second object of type <see cref="JToken"/> to compare.</param>
/// <returns>
/// true if the specified objects are equal; otherwise, false.
/// </returns>
public bool Equals(JToken x, JToken y)
{
return JToken.DeepEquals(x, y);
}
/// <summary>
/// Returns a hash code for the specified object.
/// </summary>
/// <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param>
/// <returns>A hash code for the specified object.</returns>
/// <exception cref="T:System.ArgumentNullException">The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.</exception>
public int GetHashCode(JToken obj)
{
if (obj == null)
{
return 0;
}
return obj.GetDeepHashCode();
}
}
}

View File

@@ -0,0 +1,330 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Represents a reader that provides fast, non-cached, forward-only access to serialized JSON data.
/// </summary>
public class JTokenReader : JsonReader, IJsonLineInfo
{
private readonly string _initialPath;
private readonly JToken _root;
private JToken _parent;
private JToken _current;
/// <summary>
/// Gets the <see cref="JToken"/> at the reader's current position.
/// </summary>
public JToken CurrentToken
{
get { return _current; }
}
/// <summary>
/// Initializes a new instance of the <see cref="JTokenReader"/> class.
/// </summary>
/// <param name="token">The token to read from.</param>
public JTokenReader(JToken token)
{
ValidationUtils.ArgumentNotNull(token, nameof(token));
_root = token;
}
internal JTokenReader(JToken token, string initialPath)
: this(token)
{
_initialPath = initialPath;
}
/// <summary>
/// Reads the next JSON token from the stream.
/// </summary>
/// <returns>
/// true if the next token was read successfully; false if there are no more tokens to read.
/// </returns>
public override bool Read()
{
if (CurrentState != State.Start)
{
if (_current == null)
{
return false;
}
JContainer container = _current as JContainer;
if (container != null && _parent != container)
{
return ReadInto(container);
}
else
{
return ReadOver(_current);
}
}
_current = _root;
SetToken(_current);
return true;
}
private bool ReadOver(JToken t)
{
if (t == _root)
{
return ReadToEnd();
}
JToken next = t.Next;
if ((next == null || next == t) || t == t.Parent.Last)
{
if (t.Parent == null)
{
return ReadToEnd();
}
return SetEnd(t.Parent);
}
else
{
_current = next;
SetToken(_current);
return true;
}
}
private bool ReadToEnd()
{
_current = null;
SetToken(JsonToken.None);
return false;
}
private JsonToken? GetEndToken(JContainer c)
{
switch (c.Type)
{
case JTokenType.Object:
return JsonToken.EndObject;
case JTokenType.Array:
return JsonToken.EndArray;
case JTokenType.Constructor:
return JsonToken.EndConstructor;
case JTokenType.Property:
return null;
default:
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", c.Type, "Unexpected JContainer type.");
}
}
private bool ReadInto(JContainer c)
{
JToken firstChild = c.First;
if (firstChild == null)
{
return SetEnd(c);
}
else
{
SetToken(firstChild);
_current = firstChild;
_parent = c;
return true;
}
}
private bool SetEnd(JContainer c)
{
JsonToken? endToken = GetEndToken(c);
if (endToken != null)
{
SetToken(endToken.GetValueOrDefault());
_current = c;
_parent = c;
return true;
}
else
{
return ReadOver(c);
}
}
private void SetToken(JToken token)
{
switch (token.Type)
{
case JTokenType.Object:
SetToken(JsonToken.StartObject);
break;
case JTokenType.Array:
SetToken(JsonToken.StartArray);
break;
case JTokenType.Constructor:
SetToken(JsonToken.StartConstructor, ((JConstructor)token).Name);
break;
case JTokenType.Property:
SetToken(JsonToken.PropertyName, ((JProperty)token).Name);
break;
case JTokenType.Comment:
SetToken(JsonToken.Comment, ((JValue)token).Value);
break;
case JTokenType.Integer:
SetToken(JsonToken.Integer, ((JValue)token).Value);
break;
case JTokenType.Float:
SetToken(JsonToken.Float, ((JValue)token).Value);
break;
case JTokenType.String:
SetToken(JsonToken.String, ((JValue)token).Value);
break;
case JTokenType.Boolean:
SetToken(JsonToken.Boolean, ((JValue)token).Value);
break;
case JTokenType.Null:
SetToken(JsonToken.Null, ((JValue)token).Value);
break;
case JTokenType.Undefined:
SetToken(JsonToken.Undefined, ((JValue)token).Value);
break;
case JTokenType.Date:
SetToken(JsonToken.Date, ((JValue)token).Value);
break;
case JTokenType.Raw:
SetToken(JsonToken.Raw, ((JValue)token).Value);
break;
case JTokenType.Bytes:
SetToken(JsonToken.Bytes, ((JValue)token).Value);
break;
case JTokenType.Guid:
SetToken(JsonToken.String, SafeToString(((JValue)token).Value));
break;
case JTokenType.Uri:
object v = ((JValue)token).Value;
if (v is Uri)
{
SetToken(JsonToken.String, ((Uri)v).OriginalString);
}
else
{
SetToken(JsonToken.String, SafeToString(v));
}
break;
case JTokenType.TimeSpan:
SetToken(JsonToken.String, SafeToString(((JValue)token).Value));
break;
default:
throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", token.Type, "Unexpected JTokenType.");
}
}
private string SafeToString(object value)
{
return (value != null) ? value.ToString() : null;
}
bool IJsonLineInfo.HasLineInfo()
{
if (CurrentState == State.Start)
{
return false;
}
IJsonLineInfo info = _current;
return (info != null && info.HasLineInfo());
}
int IJsonLineInfo.LineNumber
{
get
{
if (CurrentState == State.Start)
{
return 0;
}
IJsonLineInfo info = _current;
if (info != null)
{
return info.LineNumber;
}
return 0;
}
}
int IJsonLineInfo.LinePosition
{
get
{
if (CurrentState == State.Start)
{
return 0;
}
IJsonLineInfo info = _current;
if (info != null)
{
return info.LinePosition;
}
return 0;
}
}
/// <summary>
/// Gets the path of the current JSON token.
/// </summary>
public override string Path
{
get
{
string path = base.Path;
if (!string.IsNullOrEmpty(_initialPath))
{
if (string.IsNullOrEmpty(path))
{
return _initialPath;
}
if (path.StartsWith('['))
{
path = _initialPath + path;
}
else
{
path = _initialPath + "." + path;
}
}
return path;
}
}
}
}

View File

@@ -0,0 +1,123 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Specifies the type of token.
/// </summary>
public enum JTokenType
{
/// <summary>
/// No token type has been set.
/// </summary>
None = 0,
/// <summary>
/// A JSON object.
/// </summary>
Object = 1,
/// <summary>
/// A JSON array.
/// </summary>
Array = 2,
/// <summary>
/// A JSON constructor.
/// </summary>
Constructor = 3,
/// <summary>
/// A JSON object property.
/// </summary>
Property = 4,
/// <summary>
/// A comment.
/// </summary>
Comment = 5,
/// <summary>
/// An integer value.
/// </summary>
Integer = 6,
/// <summary>
/// A float value.
/// </summary>
Float = 7,
/// <summary>
/// A string value.
/// </summary>
String = 8,
/// <summary>
/// A boolean value.
/// </summary>
Boolean = 9,
/// <summary>
/// A null value.
/// </summary>
Null = 10,
/// <summary>
/// An undefined value.
/// </summary>
Undefined = 11,
/// <summary>
/// A date value.
/// </summary>
Date = 12,
/// <summary>
/// A raw JSON value.
/// </summary>
Raw = 13,
/// <summary>
/// A collection of bytes value.
/// </summary>
Bytes = 14,
/// <summary>
/// A Guid value.
/// </summary>
Guid = 15,
/// <summary>
/// A Uri value.
/// </summary>
Uri = 16,
/// <summary>
/// A TimeSpan value.
/// </summary>
TimeSpan = 17
}
}

View File

@@ -0,0 +1,489 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Globalization;
#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
using System.Numerics;
#endif
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data.
/// </summary>
public class JTokenWriter : JsonWriter
{
private JContainer _token;
private JContainer _parent;
// used when writer is writing single value and the value has no containing parent
private JValue _value;
private JToken _current;
/// <summary>
/// Gets the <see cref="JToken"/> at the writer's current position.
/// </summary>
public JToken CurrentToken
{
get { return _current; }
}
/// <summary>
/// Gets the token being writen.
/// </summary>
/// <value>The token being writen.</value>
public JToken Token
{
get
{
if (_token != null)
{
return _token;
}
return _value;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="JTokenWriter"/> class writing to the given <see cref="JContainer"/>.
/// </summary>
/// <param name="container">The container being written to.</param>
public JTokenWriter(JContainer container)
{
ValidationUtils.ArgumentNotNull(container, nameof(container));
_token = container;
_parent = container;
}
/// <summary>
/// Initializes a new instance of the <see cref="JTokenWriter"/> class.
/// </summary>
public JTokenWriter()
{
}
/// <summary>
/// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
/// </summary>
public override void Flush()
{
}
/// <summary>
/// Closes this stream and the underlying stream.
/// </summary>
public override void Close()
{
base.Close();
}
/// <summary>
/// Writes the beginning of a JSON object.
/// </summary>
public override void WriteStartObject()
{
base.WriteStartObject();
AddParent(new JObject());
}
private void AddParent(JContainer container)
{
if (_parent == null)
{
_token = container;
}
else
{
_parent.AddAndSkipParentCheck(container);
}
_parent = container;
_current = container;
}
private void RemoveParent()
{
_current = _parent;
_parent = _parent.Parent;
if (_parent != null && _parent.Type == JTokenType.Property)
{
_parent = _parent.Parent;
}
}
/// <summary>
/// Writes the beginning of a JSON array.
/// </summary>
public override void WriteStartArray()
{
base.WriteStartArray();
AddParent(new JArray());
}
/// <summary>
/// Writes the start of a constructor with the given name.
/// </summary>
/// <param name="name">The name of the constructor.</param>
public override void WriteStartConstructor(string name)
{
base.WriteStartConstructor(name);
AddParent(new JConstructor(name));
}
/// <summary>
/// Writes the end.
/// </summary>
/// <param name="token">The token.</param>
protected override void WriteEnd(JsonToken token)
{
RemoveParent();
}
/// <summary>
/// Writes the property name of a name/value pair on a JSON object.
/// </summary>
/// <param name="name">The name of the property.</param>
public override void WritePropertyName(string name)
{
JObject o = _parent as JObject;
if (o != null)
{
// avoid duplicate property name exception
// last property name wins
o.Remove(name);
}
AddParent(new JProperty(name));
// don't set state until after in case of an error
// incorrect state will cause issues if writer is disposed when closing open properties
base.WritePropertyName(name);
}
private void AddValue(object value, JsonToken token)
{
AddValue(new JValue(value), token);
}
internal void AddValue(JValue value, JsonToken token)
{
if (_parent != null)
{
_parent.Add(value);
_current = _parent.Last;
if (_parent.Type == JTokenType.Property)
{
_parent = _parent.Parent;
}
}
else
{
_value = value ?? JValue.CreateNull();
_current = _value;
}
}
#region WriteValue methods
/// <summary>
/// Writes a <see cref="Object"/> value.
/// An error will raised if the value cannot be written as a single JSON token.
/// </summary>
/// <param name="value">The <see cref="Object"/> value to write.</param>
public override void WriteValue(object value)
{
#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
if (value is BigInteger)
{
InternalWriteValue(JsonToken.Integer);
AddValue(value, JsonToken.Integer);
}
else
#endif
{
base.WriteValue(value);
}
}
/// <summary>
/// Writes a null value.
/// </summary>
public override void WriteNull()
{
base.WriteNull();
AddValue(null, JsonToken.Null);
}
/// <summary>
/// Writes an undefined value.
/// </summary>
public override void WriteUndefined()
{
base.WriteUndefined();
AddValue(null, JsonToken.Undefined);
}
/// <summary>
/// Writes raw JSON.
/// </summary>
/// <param name="json">The raw JSON to write.</param>
public override void WriteRaw(string json)
{
base.WriteRaw(json);
AddValue(new JRaw(json), JsonToken.Raw);
}
/// <summary>
/// Writes out a comment <code>/*...*/</code> containing the specified text.
/// </summary>
/// <param name="text">Text to place inside the comment.</param>
public override void WriteComment(string text)
{
base.WriteComment(text);
AddValue(JValue.CreateComment(text), JsonToken.Comment);
}
/// <summary>
/// Writes a <see cref="String"/> value.
/// </summary>
/// <param name="value">The <see cref="String"/> value to write.</param>
public override void WriteValue(string value)
{
base.WriteValue(value);
AddValue(value, JsonToken.String);
}
/// <summary>
/// Writes a <see cref="Int32"/> value.
/// </summary>
/// <param name="value">The <see cref="Int32"/> value to write.</param>
public override void WriteValue(int value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="UInt32"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt32"/> value to write.</param>
[CLSCompliant(false)]
public override void WriteValue(uint value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Int64"/> value.
/// </summary>
/// <param name="value">The <see cref="Int64"/> value to write.</param>
public override void WriteValue(long value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="UInt64"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt64"/> value to write.</param>
[CLSCompliant(false)]
public override void WriteValue(ulong value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Single"/> value.
/// </summary>
/// <param name="value">The <see cref="Single"/> value to write.</param>
public override void WriteValue(float value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Float);
}
/// <summary>
/// Writes a <see cref="Double"/> value.
/// </summary>
/// <param name="value">The <see cref="Double"/> value to write.</param>
public override void WriteValue(double value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Float);
}
/// <summary>
/// Writes a <see cref="Boolean"/> value.
/// </summary>
/// <param name="value">The <see cref="Boolean"/> value to write.</param>
public override void WriteValue(bool value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Boolean);
}
/// <summary>
/// Writes a <see cref="Int16"/> value.
/// </summary>
/// <param name="value">The <see cref="Int16"/> value to write.</param>
public override void WriteValue(short value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="UInt16"/> value.
/// </summary>
/// <param name="value">The <see cref="UInt16"/> value to write.</param>
[CLSCompliant(false)]
public override void WriteValue(ushort value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Char"/> value.
/// </summary>
/// <param name="value">The <see cref="Char"/> value to write.</param>
public override void WriteValue(char value)
{
base.WriteValue(value);
string s = null;
#if !(DOTNET || PORTABLE40 || PORTABLE)
s = value.ToString(CultureInfo.InvariantCulture);
#else
s = value.ToString();
#endif
AddValue(s, JsonToken.String);
}
/// <summary>
/// Writes a <see cref="Byte"/> value.
/// </summary>
/// <param name="value">The <see cref="Byte"/> value to write.</param>
public override void WriteValue(byte value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="SByte"/> value.
/// </summary>
/// <param name="value">The <see cref="SByte"/> value to write.</param>
[CLSCompliant(false)]
public override void WriteValue(sbyte value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Integer);
}
/// <summary>
/// Writes a <see cref="Decimal"/> value.
/// </summary>
/// <param name="value">The <see cref="Decimal"/> value to write.</param>
public override void WriteValue(decimal value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Float);
}
/// <summary>
/// Writes a <see cref="DateTime"/> value.
/// </summary>
/// <param name="value">The <see cref="DateTime"/> value to write.</param>
public override void WriteValue(DateTime value)
{
base.WriteValue(value);
value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling);
AddValue(value, JsonToken.Date);
}
#if !NET20
/// <summary>
/// Writes a <see cref="DateTimeOffset"/> value.
/// </summary>
/// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
public override void WriteValue(DateTimeOffset value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Date);
}
#endif
/// <summary>
/// Writes a <see cref="Byte"/>[] value.
/// </summary>
/// <param name="value">The <see cref="Byte"/>[] value to write.</param>
public override void WriteValue(byte[] value)
{
base.WriteValue(value);
AddValue(value, JsonToken.Bytes);
}
/// <summary>
/// Writes a <see cref="TimeSpan"/> value.
/// </summary>
/// <param name="value">The <see cref="TimeSpan"/> value to write.</param>
public override void WriteValue(TimeSpan value)
{
base.WriteValue(value);
AddValue(value, JsonToken.String);
}
/// <summary>
/// Writes a <see cref="Guid"/> value.
/// </summary>
/// <param name="value">The <see cref="Guid"/> value to write.</param>
public override void WriteValue(Guid value)
{
base.WriteValue(value);
AddValue(value, JsonToken.String);
}
/// <summary>
/// Writes a <see cref="Uri"/> value.
/// </summary>
/// <param name="value">The <see cref="Uri"/> value to write.</param>
public override void WriteValue(Uri value)
{
base.WriteValue(value);
AddValue(value, JsonToken.String);
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
using System;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Specifies the settings used when loading JSON.
/// </summary>
public class JsonLoadSettings
{
private CommentHandling _commentHandling;
private LineInfoHandling _lineInfoHandling;
/// <summary>
/// Gets or sets how JSON comments are handled when loading JSON.
/// </summary>
/// <value>The JSON comment handling.</value>
public CommentHandling CommentHandling
{
get { return _commentHandling; }
set
{
if (value < CommentHandling.Ignore || value > CommentHandling.Load)
{
throw new ArgumentOutOfRangeException(nameof(value));
}
_commentHandling = value;
}
}
/// <summary>
/// Gets or sets how JSON line info is handled when loading JSON.
/// </summary>
/// <value>The JSON line info handling.</value>
public LineInfoHandling LineInfoHandling
{
get { return _lineInfoHandling; }
set
{
if (value < LineInfoHandling.Ignore || value > LineInfoHandling.Load)
{
throw new ArgumentOutOfRangeException(nameof(value));
}
_lineInfoHandling = value;
}
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Specifies the settings used when merging JSON.
/// </summary>
public class JsonMergeSettings
{
private MergeArrayHandling _mergeArrayHandling;
private MergeNullValueHandling _mergeNullValueHandling;
/// <summary>
/// Gets or sets the method used when merging JSON arrays.
/// </summary>
/// <value>The method used when merging JSON arrays.</value>
public MergeArrayHandling MergeArrayHandling
{
get { return _mergeArrayHandling; }
set
{
if (value < MergeArrayHandling.Concat || value > MergeArrayHandling.Merge)
{
throw new ArgumentOutOfRangeException(nameof(value));
}
_mergeArrayHandling = value;
}
}
/// <summary>
/// Gets or sets how how null value properties are merged.
/// </summary>
/// <value>How null value properties are merged.</value>
public MergeNullValueHandling MergeNullValueHandling
{
get { return _mergeNullValueHandling; }
set
{
if (value < MergeNullValueHandling.Ignore || value > MergeNullValueHandling.Merge)
{
throw new ArgumentOutOfRangeException(nameof(value));
}
_mergeNullValueHandling = value;
}
}
}
}

View File

@@ -0,0 +1,44 @@
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq.JsonPath
{
internal class ArrayIndexFilter : PathFilter
{
public int? Index { get; set; }
public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
{
foreach (JToken t in current)
{
if (Index != null)
{
JToken v = GetTokenIndex(t, errorWhenNoMatch, Index.GetValueOrDefault());
if (v != null)
{
yield return v;
}
}
else
{
if (t is JArray || t is JConstructor)
{
foreach (JToken v in t)
{
yield return v;
}
}
else
{
if (errorWhenNoMatch)
{
throw new JsonException("Index * not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, t.GetType().Name));
}
}
}
}
}
}
}

View File

@@ -0,0 +1,25 @@
using System.Collections.Generic;
namespace Newtonsoft.Json.Linq.JsonPath
{
internal class ArrayMultipleIndexFilter : PathFilter
{
public List<int> Indexes { get; set; }
public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
{
foreach (JToken t in current)
{
foreach (int i in Indexes)
{
JToken v = GetTokenIndex(t, errorWhenNoMatch, i);
if (v != null)
{
yield return v;
}
}
}
}
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq.JsonPath
{
internal class ArraySliceFilter : PathFilter
{
public int? Start { get; set; }
public int? End { get; set; }
public int? Step { get; set; }
public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
{
if (Step == 0)
{
throw new JsonException("Step cannot be zero.");
}
foreach (JToken t in current)
{
JArray a = t as JArray;
if (a != null)
{
// set defaults for null arguments
int stepCount = Step ?? 1;
int startIndex = Start ?? ((stepCount > 0) ? 0 : a.Count - 1);
int stopIndex = End ?? ((stepCount > 0) ? a.Count : -1);
// start from the end of the list if start is negitive
if (Start < 0)
{
startIndex = a.Count + startIndex;
}
// end from the start of the list if stop is negitive
if (End < 0)
{
stopIndex = a.Count + stopIndex;
}
// ensure indexes keep within collection bounds
startIndex = Math.Max(startIndex, (stepCount > 0) ? 0 : int.MinValue);
startIndex = Math.Min(startIndex, (stepCount > 0) ? a.Count : a.Count - 1);
stopIndex = Math.Max(stopIndex, -1);
stopIndex = Math.Min(stopIndex, a.Count);
bool positiveStep = (stepCount > 0);
if (IsValid(startIndex, stopIndex, positiveStep))
{
for (int i = startIndex; IsValid(i, stopIndex, positiveStep); i += stepCount)
{
yield return a[i];
}
}
else
{
if (errorWhenNoMatch)
{
throw new JsonException("Array slice of {0} to {1} returned no results.".FormatWith(CultureInfo.InvariantCulture,
Start != null ? Start.GetValueOrDefault().ToString(CultureInfo.InvariantCulture) : "*",
End != null ? End.GetValueOrDefault().ToString(CultureInfo.InvariantCulture) : "*"));
}
}
}
else
{
if (errorWhenNoMatch)
{
throw new JsonException("Array slice is not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, t.GetType().Name));
}
}
}
}
private bool IsValid(int index, int stopIndex, bool positiveStep)
{
if (positiveStep)
{
return (index < stopIndex);
}
return (index > stopIndex);
}
}
}

View File

@@ -0,0 +1,49 @@
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq.JsonPath
{
internal class FieldFilter : PathFilter
{
public string Name { get; set; }
public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
{
foreach (JToken t in current)
{
JObject o = t as JObject;
if (o != null)
{
if (Name != null)
{
JToken v = o[Name];
if (v != null)
{
yield return v;
}
else if (errorWhenNoMatch)
{
throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, Name));
}
}
else
{
foreach (KeyValuePair<string, JToken> p in o)
{
yield return p.Value;
}
}
}
else
{
if (errorWhenNoMatch)
{
throw new JsonException("Property '{0}' not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, Name ?? "*", t.GetType().Name));
}
}
}
}
}
}

View File

@@ -0,0 +1,48 @@
using System.Collections.Generic;
using System.Globalization;
#if NET20
using Newtonsoft.Json.Utilities.LinqBridge;
#else
using System.Linq;
#endif
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq.JsonPath
{
internal class FieldMultipleFilter : PathFilter
{
public List<string> Names { get; set; }
public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
{
foreach (JToken t in current)
{
JObject o = t as JObject;
if (o != null)
{
foreach (string name in Names)
{
JToken v = o[name];
if (v != null)
{
yield return v;
}
if (errorWhenNoMatch)
{
throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, name));
}
}
}
else
{
if (errorWhenNoMatch)
{
throw new JsonException("Properties {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", Names.Select(n => "'" + n + "'").ToArray()), t.GetType().Name));
}
}
}
}
}
}

View File

@@ -0,0 +1,777 @@
#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq.JsonPath
{
internal class JPath
{
private readonly string _expression;
public List<PathFilter> Filters { get; private set; }
private int _currentIndex;
public JPath(string expression)
{
ValidationUtils.ArgumentNotNull(expression, nameof(expression));
_expression = expression;
Filters = new List<PathFilter>();
ParseMain();
}
private void ParseMain()
{
int currentPartStartIndex = _currentIndex;
EatWhitespace();
if (_expression.Length == _currentIndex)
{
return;
}
if (_expression[_currentIndex] == '$')
{
if (_expression.Length == 1)
{
return;
}
// only increment position for "$." or "$["
// otherwise assume property that starts with $
char c = _expression[_currentIndex + 1];
if (c == '.' || c == '[')
{
_currentIndex++;
currentPartStartIndex = _currentIndex;
}
}
if (!ParsePath(Filters, currentPartStartIndex, false))
{
int lastCharacterIndex = _currentIndex;
EatWhitespace();
if (_currentIndex < _expression.Length)
{
throw new JsonException("Unexpected character while parsing path: " + _expression[lastCharacterIndex]);
}
}
}
private bool ParsePath(List<PathFilter> filters, int currentPartStartIndex, bool query)
{
bool scan = false;
bool followingIndexer = false;
bool followingDot = false;
bool ended = false;
while (_currentIndex < _expression.Length && !ended)
{
char currentChar = _expression[_currentIndex];
switch (currentChar)
{
case '[':
case '(':
if (_currentIndex > currentPartStartIndex)
{
string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex);
if (member == "*")
{
member = null;
}
PathFilter filter = (scan) ? (PathFilter)new ScanFilter { Name = member } : new FieldFilter { Name = member };
filters.Add(filter);
scan = false;
}
filters.Add(ParseIndexer(currentChar));
_currentIndex++;
currentPartStartIndex = _currentIndex;
followingIndexer = true;
followingDot = false;
break;
case ']':
case ')':
ended = true;
break;
case ' ':
if (_currentIndex < _expression.Length)
{
ended = true;
}
break;
case '.':
if (_currentIndex > currentPartStartIndex)
{
string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex);
if (member == "*")
{
member = null;
}
PathFilter filter = (scan) ? (PathFilter)new ScanFilter { Name = member } : new FieldFilter { Name = member };
filters.Add(filter);
scan = false;
}
if (_currentIndex + 1 < _expression.Length && _expression[_currentIndex + 1] == '.')
{
scan = true;
_currentIndex++;
}
_currentIndex++;
currentPartStartIndex = _currentIndex;
followingIndexer = false;
followingDot = true;
break;
default:
if (query && (currentChar == '=' || currentChar == '<' || currentChar == '!' || currentChar == '>' || currentChar == '|' || currentChar == '&'))
{
ended = true;
}
else
{
if (followingIndexer)
{
throw new JsonException("Unexpected character following indexer: " + currentChar);
}
_currentIndex++;
}
break;
}
}
bool atPathEnd = (_currentIndex == _expression.Length);
if (_currentIndex > currentPartStartIndex)
{
string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex).TrimEnd();
if (member == "*")
{
member = null;
}
PathFilter filter = (scan) ? (PathFilter)new ScanFilter { Name = member } : new FieldFilter { Name = member };
filters.Add(filter);
}
else
{
// no field name following dot in path and at end of base path/query
if (followingDot && (atPathEnd || query))
{
throw new JsonException("Unexpected end while parsing path.");
}
}
return atPathEnd;
}
private PathFilter ParseIndexer(char indexerOpenChar)
{
_currentIndex++;
char indexerCloseChar = (indexerOpenChar == '[') ? ']' : ')';
EnsureLength("Path ended with open indexer.");
EatWhitespace();
if (_expression[_currentIndex] == '\'')
{
return ParseQuotedField(indexerCloseChar);
}
else if (_expression[_currentIndex] == '?')
{
return ParseQuery(indexerCloseChar);
}
else
{
return ParseArrayIndexer(indexerCloseChar);
}
}
private PathFilter ParseArrayIndexer(char indexerCloseChar)
{
int start = _currentIndex;
int? end = null;
List<int> indexes = null;
int colonCount = 0;
int? startIndex = null;
int? endIndex = null;
int? step = null;
while (_currentIndex < _expression.Length)
{
char currentCharacter = _expression[_currentIndex];
if (currentCharacter == ' ')
{
end = _currentIndex;
EatWhitespace();
continue;
}
if (currentCharacter == indexerCloseChar)
{
int length = (end ?? _currentIndex) - start;
if (indexes != null)
{
if (length == 0)
{
throw new JsonException("Array index expected.");
}
string indexer = _expression.Substring(start, length);
int index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture);
indexes.Add(index);
return new ArrayMultipleIndexFilter { Indexes = indexes };
}
else if (colonCount > 0)
{
if (length > 0)
{
string indexer = _expression.Substring(start, length);
int index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture);
if (colonCount == 1)
{
endIndex = index;
}
else
{
step = index;
}
}
return new ArraySliceFilter { Start = startIndex, End = endIndex, Step = step };
}
else
{
if (length == 0)
{
throw new JsonException("Array index expected.");
}
string indexer = _expression.Substring(start, length);
int index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture);
return new ArrayIndexFilter { Index = index };
}
}
else if (currentCharacter == ',')
{
int length = (end ?? _currentIndex) - start;
if (length == 0)
{
throw new JsonException("Array index expected.");
}
if (indexes == null)
{
indexes = new List<int>();
}
string indexer = _expression.Substring(start, length);
indexes.Add(Convert.ToInt32(indexer, CultureInfo.InvariantCulture));
_currentIndex++;
EatWhitespace();
start = _currentIndex;
end = null;
}
else if (currentCharacter == '*')
{
_currentIndex++;
EnsureLength("Path ended with open indexer.");
EatWhitespace();
if (_expression[_currentIndex] != indexerCloseChar)
{
throw new JsonException("Unexpected character while parsing path indexer: " + currentCharacter);
}
return new ArrayIndexFilter();
}
else if (currentCharacter == ':')
{
int length = (end ?? _currentIndex) - start;
if (length > 0)
{
string indexer = _expression.Substring(start, length);
int index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture);
if (colonCount == 0)
{
startIndex = index;
}
else if (colonCount == 1)
{
endIndex = index;
}
else
{
step = index;
}
}
colonCount++;
_currentIndex++;
EatWhitespace();
start = _currentIndex;
end = null;
}
else if (!char.IsDigit(currentCharacter) && currentCharacter != '-')
{
throw new JsonException("Unexpected character while parsing path indexer: " + currentCharacter);
}
else
{
if (end != null)
{
throw new JsonException("Unexpected character while parsing path indexer: " + currentCharacter);
}
_currentIndex++;
}
}
throw new JsonException("Path ended with open indexer.");
}
private void EatWhitespace()
{
while (_currentIndex < _expression.Length)
{
if (_expression[_currentIndex] != ' ')
{
break;
}
_currentIndex++;
}
}
private PathFilter ParseQuery(char indexerCloseChar)
{
_currentIndex++;
EnsureLength("Path ended with open indexer.");
if (_expression[_currentIndex] != '(')
{
throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]);
}
_currentIndex++;
QueryExpression expression = ParseExpression();
_currentIndex++;
EnsureLength("Path ended with open indexer.");
EatWhitespace();
if (_expression[_currentIndex] != indexerCloseChar)
{
throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]);
}
return new QueryFilter
{
Expression = expression
};
}
private QueryExpression ParseExpression()
{
QueryExpression rootExpression = null;
CompositeExpression parentExpression = null;
while (_currentIndex < _expression.Length)
{
EatWhitespace();
if (_expression[_currentIndex] != '@')
{
throw new JsonException("Unexpected character while parsing path query: " + _expression[_currentIndex]);
}
_currentIndex++;
List<PathFilter> expressionPath = new List<PathFilter>();
if (ParsePath(expressionPath, _currentIndex, true))
{
throw new JsonException("Path ended with open query.");
}
EatWhitespace();
EnsureLength("Path ended with open query.");
QueryOperator op;
object value = null;
if (_expression[_currentIndex] == ')'
|| _expression[_currentIndex] == '|'
|| _expression[_currentIndex] == '&')
{
op = QueryOperator.Exists;
}
else
{
op = ParseOperator();
EatWhitespace();
EnsureLength("Path ended with open query.");
value = ParseValue();
EatWhitespace();
EnsureLength("Path ended with open query.");
}
BooleanQueryExpression booleanExpression = new BooleanQueryExpression
{
Path = expressionPath,
Operator = op,
Value = (op != QueryOperator.Exists) ? new JValue(value) : null
};
if (_expression[_currentIndex] == ')')
{
if (parentExpression != null)
{
parentExpression.Expressions.Add(booleanExpression);
return rootExpression;
}
return booleanExpression;
}
if (_expression[_currentIndex] == '&' && Match("&&"))
{
if (parentExpression == null || parentExpression.Operator != QueryOperator.And)
{
CompositeExpression andExpression = new CompositeExpression { Operator = QueryOperator.And };
if (parentExpression != null)
{
parentExpression.Expressions.Add(andExpression);
}
parentExpression = andExpression;
if (rootExpression == null)
{
rootExpression = parentExpression;
}
}
parentExpression.Expressions.Add(booleanExpression);
}
if (_expression[_currentIndex] == '|' && Match("||"))
{
if (parentExpression == null || parentExpression.Operator != QueryOperator.Or)
{
CompositeExpression orExpression = new CompositeExpression { Operator = QueryOperator.Or };
if (parentExpression != null)
{
parentExpression.Expressions.Add(orExpression);
}
parentExpression = orExpression;
if (rootExpression == null)
{
rootExpression = parentExpression;
}
}
parentExpression.Expressions.Add(booleanExpression);
}
}
throw new JsonException("Path ended with open query.");
}
private object ParseValue()
{
char currentChar = _expression[_currentIndex];
if (currentChar == '\'')
{
return ReadQuotedString();
}
else if (char.IsDigit(currentChar) || currentChar == '-')
{
StringBuilder sb = new StringBuilder();
sb.Append(currentChar);
_currentIndex++;
while (_currentIndex < _expression.Length)
{
currentChar = _expression[_currentIndex];
if (currentChar == ' ' || currentChar == ')')
{
string numberText = sb.ToString();
if (numberText.IndexOfAny(new char[] { '.', 'E', 'e' }) != -1)
{
double d;
if (double.TryParse(numberText, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out d))
{
return d;
}
else
{
throw new JsonException("Could not read query value.");
}
}
else
{
long l;
if (long.TryParse(numberText, NumberStyles.Integer, CultureInfo.InvariantCulture, out l))
{
return l;
}
else
{
throw new JsonException("Could not read query value.");
}
}
}
else
{
sb.Append(currentChar);
_currentIndex++;
}
}
}
else if (currentChar == 't')
{
if (Match("true"))
{
return true;
}
}
else if (currentChar == 'f')
{
if (Match("false"))
{
return false;
}
}
else if (currentChar == 'n')
{
if (Match("null"))
{
return null;
}
}
throw new JsonException("Could not read query value.");
}
private string ReadQuotedString()
{
StringBuilder sb = new StringBuilder();
_currentIndex++;
while (_currentIndex < _expression.Length)
{
char currentChar = _expression[_currentIndex];
if (currentChar == '\\' && _currentIndex + 1 < _expression.Length)
{
_currentIndex++;
if (_expression[_currentIndex] == '\'')
{
sb.Append('\'');
}
else if (_expression[_currentIndex] == '\\')
{
sb.Append('\\');
}
else
{
throw new JsonException(@"Unknown escape chracter: \" + _expression[_currentIndex]);
}
_currentIndex++;
}
else if (currentChar == '\'')
{
_currentIndex++;
{
return sb.ToString();
}
}
else
{
_currentIndex++;
sb.Append(currentChar);
}
}
throw new JsonException("Path ended with an open string.");
}
private bool Match(string s)
{
int currentPosition = _currentIndex;
foreach (char c in s)
{
if (currentPosition < _expression.Length && _expression[currentPosition] == c)
{
currentPosition++;
}
else
{
return false;
}
}
_currentIndex = currentPosition;
return true;
}
private QueryOperator ParseOperator()
{
if (_currentIndex + 1 >= _expression.Length)
{
throw new JsonException("Path ended with open query.");
}
if (Match("=="))
{
return QueryOperator.Equals;
}
if (Match("!=") || Match("<>"))
{
return QueryOperator.NotEquals;
}
if (Match("<="))
{
return QueryOperator.LessThanOrEquals;
}
if (Match("<"))
{
return QueryOperator.LessThan;
}
if (Match(">="))
{
return QueryOperator.GreaterThanOrEquals;
}
if (Match(">"))
{
return QueryOperator.GreaterThan;
}
throw new JsonException("Could not read query operator.");
}
private PathFilter ParseQuotedField(char indexerCloseChar)
{
List<string> fields = null;
while (_currentIndex < _expression.Length)
{
string field = ReadQuotedString();
EatWhitespace();
EnsureLength("Path ended with open indexer.");
if (_expression[_currentIndex] == indexerCloseChar)
{
if (fields != null)
{
fields.Add(field);
return new FieldMultipleFilter { Names = fields };
}
else
{
return new FieldFilter { Name = field };
}
}
else if (_expression[_currentIndex] == ',')
{
_currentIndex++;
EatWhitespace();
if (fields == null)
{
fields = new List<string>();
}
fields.Add(field);
}
else
{
throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]);
}
}
throw new JsonException("Path ended with open indexer.");
}
private void EnsureLength(string message)
{
if (_currentIndex >= _expression.Length)
{
throw new JsonException(message);
}
}
internal IEnumerable<JToken> Evaluate(JToken t, bool errorWhenNoMatch)
{
return Evaluate(Filters, t, errorWhenNoMatch);
}
internal static IEnumerable<JToken> Evaluate(List<PathFilter> filters, JToken t, bool errorWhenNoMatch)
{
IEnumerable<JToken> current = new[] { t };
foreach (PathFilter filter in filters)
{
current = filter.ExecuteFilter(current, errorWhenNoMatch);
}
return current;
}
}
}

View File

@@ -0,0 +1,55 @@
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq.JsonPath
{
internal abstract class PathFilter
{
public abstract IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch);
protected static JToken GetTokenIndex(JToken t, bool errorWhenNoMatch, int index)
{
JArray a = t as JArray;
JConstructor c = t as JConstructor;
if (a != null)
{
if (a.Count <= index)
{
if (errorWhenNoMatch)
{
throw new JsonException("Index {0} outside the bounds of JArray.".FormatWith(CultureInfo.InvariantCulture, index));
}
return null;
}
return a[index];
}
else if (c != null)
{
if (c.Count <= index)
{
if (errorWhenNoMatch)
{
throw new JsonException("Index {0} outside the bounds of JConstructor.".FormatWith(CultureInfo.InvariantCulture, index));
}
return null;
}
return c[index];
}
else
{
if (errorWhenNoMatch)
{
throw new JsonException("Index {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, index, t.GetType().Name));
}
return null;
}
}
}
}

View File

@@ -0,0 +1,180 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq.JsonPath
{
internal enum QueryOperator
{
None = 0,
Equals = 1,
NotEquals = 2,
Exists = 3,
LessThan = 4,
LessThanOrEquals = 5,
GreaterThan = 6,
GreaterThanOrEquals = 7,
And = 8,
Or = 9
}
internal abstract class QueryExpression
{
public QueryOperator Operator { get; set; }
public abstract bool IsMatch(JToken t);
}
internal class CompositeExpression : QueryExpression
{
public List<QueryExpression> Expressions { get; set; }
public CompositeExpression()
{
Expressions = new List<QueryExpression>();
}
public override bool IsMatch(JToken t)
{
switch (Operator)
{
case QueryOperator.And:
foreach (QueryExpression e in Expressions)
{
if (!e.IsMatch(t))
{
return false;
}
}
return true;
case QueryOperator.Or:
foreach (QueryExpression e in Expressions)
{
if (e.IsMatch(t))
{
return true;
}
}
return false;
default:
throw new ArgumentOutOfRangeException();
}
}
}
internal class BooleanQueryExpression : QueryExpression
{
public List<PathFilter> Path { get; set; }
public JValue Value { get; set; }
public override bool IsMatch(JToken t)
{
IEnumerable<JToken> pathResult = JPath.Evaluate(Path, t, false);
foreach (JToken r in pathResult)
{
JValue v = r as JValue;
switch (Operator)
{
case QueryOperator.Equals:
if (v != null && EqualsWithStringCoercion(v, Value))
{
return true;
}
break;
case QueryOperator.NotEquals:
if (v != null && !EqualsWithStringCoercion(v, Value))
{
return true;
}
break;
case QueryOperator.GreaterThan:
if (v != null && v.CompareTo(Value) > 0)
{
return true;
}
break;
case QueryOperator.GreaterThanOrEquals:
if (v != null && v.CompareTo(Value) >= 0)
{
return true;
}
break;
case QueryOperator.LessThan:
if (v != null && v.CompareTo(Value) < 0)
{
return true;
}
break;
case QueryOperator.LessThanOrEquals:
if (v != null && v.CompareTo(Value) <= 0)
{
return true;
}
break;
case QueryOperator.Exists:
return true;
default:
throw new ArgumentOutOfRangeException();
}
}
return false;
}
private bool EqualsWithStringCoercion(JValue value, JValue queryValue)
{
if (value.Equals(queryValue))
{
return true;
}
if (queryValue.Type != JTokenType.String)
{
return false;
}
string queryValueString = (string)queryValue.Value;
string currentValueString;
// potential performance issue with converting every value to string?
switch (value.Type)
{
case JTokenType.Date:
using (StringWriter writer = StringUtils.CreateStringWriter(64))
{
#if !NET20
if (value.Value is DateTimeOffset)
{
DateTimeUtils.WriteDateTimeOffsetString(writer, (DateTimeOffset)value.Value, DateFormatHandling.IsoDateFormat, null, CultureInfo.InvariantCulture);
}
else
#endif
{
DateTimeUtils.WriteDateTimeString(writer, (DateTime)value.Value, DateFormatHandling.IsoDateFormat, null, CultureInfo.InvariantCulture);
}
currentValueString = writer.ToString();
}
break;
case JTokenType.Bytes:
currentValueString = Convert.ToBase64String((byte[])value.Value);
break;
case JTokenType.Guid:
case JTokenType.TimeSpan:
currentValueString = value.Value.ToString();
break;
case JTokenType.Uri:
currentValueString = ((Uri)value.Value).OriginalString;
break;
default:
return false;
}
return string.Equals(currentValueString, queryValueString, StringComparison.Ordinal);
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
namespace Newtonsoft.Json.Linq.JsonPath
{
internal class QueryFilter : PathFilter
{
public QueryExpression Expression { get; set; }
public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
{
foreach (JToken t in current)
{
foreach (JToken v in t)
{
if (Expression.IsMatch(v))
{
yield return v;
}
}
}
}
}
}

View File

@@ -0,0 +1,63 @@
using System.Collections.Generic;
namespace Newtonsoft.Json.Linq.JsonPath
{
internal class ScanFilter : PathFilter
{
public string Name { get; set; }
public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
{
foreach (JToken root in current)
{
if (Name == null)
{
yield return root;
}
JToken value = root;
JToken container = root;
while (true)
{
if (container != null && container.HasValues)
{
value = container.First;
}
else
{
while (value != null && value != root && value == value.Parent.Last)
{
value = value.Parent;
}
if (value == null || value == root)
{
break;
}
value = value.Next;
}
JProperty e = value as JProperty;
if (e != null)
{
if (e.Name == Name)
{
yield return e.Value;
}
}
else
{
if (Name == null)
{
yield return value;
}
}
container = value as JContainer;
}
}
}
}
}

View File

@@ -0,0 +1,20 @@
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Specifies how JSON arrays are merged together.
/// </summary>
public enum MergeArrayHandling
{
/// <summary>Concatenate arrays.</summary>
Concat = 0,
/// <summary>Union arrays, skipping items that already exist.</summary>
Union = 1,
/// <summary>Replace all array items.</summary>
Replace = 2,
/// <summary>Merge array items together, matched by index.</summary>
Merge = 3
}
}

View File

@@ -0,0 +1,21 @@
using System;
namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Specifies how null value properties are merged.
/// </summary>
[Flags]
public enum MergeNullValueHandling
{
/// <summary>
/// The content's null value properties will be ignored during merging.
/// </summary>
Ignore = 0,
/// <summary>
/// The content's null value properties will be merged.
/// </summary>
Merge = 1
}
}