#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.Linq;
using System.IO;
using Newtonsoft.Json.Utilities;
using System.Diagnostics;
using System.Globalization;
using System.Collections;
using System.ComponentModel;
namespace Newtonsoft.Json.Linq
{
///
/// Represents an abstract JSON token.
///
public abstract class JToken : IJEnumerable, IJsonLineInfo
{
private JContainer _parent;
internal JToken _next;
private static JTokenEqualityComparer _equalityComparer;
private int? _lineNumber;
private int? _linePosition;
///
/// Gets a comparer that can compare two tokens for value equality.
///
/// A that can compare two nodes for value equality.
public static JTokenEqualityComparer EqualityComparer
{
get
{
if (_equalityComparer == null)
_equalityComparer = new JTokenEqualityComparer();
return _equalityComparer;
}
}
///
/// Gets or sets the parent.
///
/// The parent.
public JContainer Parent
{
[DebuggerStepThrough]
get { return _parent; }
internal set { _parent = value; }
}
///
/// Gets the root of this .
///
/// The root of this .
public JToken Root
{
get
{
JContainer parent = Parent;
if (parent == null)
return this;
while (parent.Parent != null)
{
parent = parent.Parent;
}
return parent;
}
}
internal abstract JToken CloneToken();
internal abstract bool DeepEquals(JToken node);
///
/// Gets the node type for this .
///
/// The type.
public abstract JTokenType Type { get; }
///
/// Gets a value indicating whether this token has childen tokens.
///
///
/// true if this token has child values; otherwise, false.
///
public abstract bool HasValues { get; }
///
/// Compares the values of two tokens, including the values of all descendant tokens.
///
/// The first to compare.
/// The second to compare.
/// true if the tokens are equal; otherwise false.
public static bool DeepEquals(JToken t1, JToken t2)
{
return (t1 == t2 || (t1 != null && t2 != null && t1.DeepEquals(t2)));
}
///
/// Gets the next sibling token of this node.
///
/// The that contains the next sibling token.
public JToken Next
{
get
{
if (_parent != null && _next != _parent.First)
return _next;
return null;
}
internal set { _next = value; }
}
///
/// Gets the previous sibling token of this node.
///
/// The that contains the previous sibling token.
public JToken Previous
{
get
{
if (_parent == null)
return null;
JToken parentNext = _parent.Content._next;
JToken parentNextBefore = null;
while (parentNext != this)
{
parentNextBefore = parentNext;
parentNext = parentNext.Next;
}
return parentNextBefore;
}
}
internal JToken()
{
}
///
/// Adds the specified content immediately after this token.
///
/// A content object that contains simple content or a collection of content objects to be added after this token.
public void AddAfterSelf(object content)
{
if (_parent == null)
throw new InvalidOperationException("The parent is missing.");
_parent.AddInternal((Next == null), this, content);
}
///
/// Adds the specified content immediately before this token.
///
/// A content object that contains simple content or a collection of content objects to be added before this token.
public void AddBeforeSelf(object content)
{
if (_parent == null)
throw new InvalidOperationException("The parent is missing.");
JToken previous = Previous;
if (previous == null)
previous = _parent.Last;
_parent.AddInternal(false, previous, content);
}
///
/// Returns a collection of the ancestor tokens of this token.
///
/// A collection of the ancestor tokens of this token.
public IEnumerable Ancestors()
{
for (JToken parent = Parent; parent != null; parent = parent.Parent)
{
yield return parent;
}
}
///
/// Returns a collection of the sibling tokens after this token, in document order.
///
/// A collection of the sibling tokens after this tokens, in document order.
public IEnumerable AfterSelf()
{
if (Parent == null)
yield break;
for (JToken o = Next; o != null; o = o.Next)
yield return o;
}
///
/// Returns a collection of the sibling tokens before this token, in document order.
///
/// A collection of the sibling tokens before this token, in document order.
public IEnumerable BeforeSelf()
{
for (JToken o = Parent.First; o != this; o = o.Next)
yield return o;
}
///
/// Gets the with the specified key.
///
/// The with the specified key.
public virtual JToken this[object key]
{
get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); }
set { throw new InvalidOperationException("Cannot set child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); }
}
///
/// Gets the with the specified key converted to the specified type.
///
/// The type to convert the token to.
/// The token key.
/// The converted token value.
public virtual T Value(object key)
{
JToken token = this[key];
return Extensions.Convert(token);
}
///
/// Get the first child token of this token.
///
/// A containing the first child token of the .
public virtual JToken First
{
get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); }
}
///
/// Get the last child token of this token.
///
/// A containing the last child token of the .
public virtual JToken Last
{
get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); }
}
///
/// Returns a collection of the child tokens of this token, in document order.
///
/// An of containing the child tokens of this , in document order.
public virtual JEnumerable Children()
{
throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
}
///
/// Returns a collection of the child tokens of this token, in document order, filtered by the specified type.
///
/// The type to filter the child tokens on.
/// A containing the child tokens of this , in document order.
public JEnumerable Children() where T : JToken
{
return new JEnumerable(Children().OfType());
}
///
/// Returns a collection of the child values of this token, in document order.
///
/// The type to convert the values to.
/// A containing the child values of this , in document order.
public virtual IEnumerable Values()
{
throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
}
///
/// Removes this token from its parent.
///
public void Remove()
{
if (_parent == null)
throw new InvalidOperationException("The parent is missing.");
_parent.RemoveItem(this);
}
///
/// Replaces this token with the specified token.
///
/// The value.
public void Replace(JToken value)
{
if (_parent == null)
throw new InvalidOperationException("The parent is missing.");
_parent.ReplaceItem(this, value);
}
///
/// Writes this token to a .
///
/// A into which this method will write.
/// A collection of which will be used when writing the token.
public abstract void WriteTo(JsonWriter writer, params JsonConverter[] converters);
///
/// Returns the indented JSON for this token.
///
///
/// The indented JSON for this token.
///
public override string ToString()
{
return ToString(Formatting.Indented);
}
///
/// Returns the JSON for this token using the given formatting and converters.
///
/// Indicates how the output is formatted.
/// A collection of which will be used when writing the token.
/// The JSON for this token using the given formatting and converters.
public string ToString(Formatting formatting, params JsonConverter[] converters)
{
using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture))
{
JsonTextWriter jw = new JsonTextWriter(sw);
jw.Formatting = formatting;
WriteTo(jw, converters);
return sw.ToString();
}
}
private static JValue EnsureValue(JToken value)
{
if (value == null)
throw new ArgumentNullException("value");
if (value is JProperty)
value = ((JProperty)value).Value;
JValue v = value as JValue;
return v;
}
private static string GetType(JToken token)
{
ValidationUtils.ArgumentNotNull(token, "token");
if (token is JProperty)
token = ((JProperty)token).Value;
return token.Type.ToString();
}
private static bool IsNullable(JToken o)
{
return (o.Type == JTokenType.Undefined || o.Type == JTokenType.Null);
}
private static bool ValidateFloat(JToken o, bool nullable)
{
return (o.Type == JTokenType.Float || o.Type == JTokenType.Integer || (nullable && IsNullable(o)));
}
private static bool ValidateInteger(JToken o, bool nullable)
{
return (o.Type == JTokenType.Integer || (nullable && IsNullable(o)));
}
private static bool ValidateDate(JToken o, bool nullable)
{
return (o.Type == JTokenType.Date || (nullable && IsNullable(o)));
}
private static bool ValidateBoolean(JToken o, bool nullable)
{
return (o.Type == JTokenType.Boolean || (nullable && IsNullable(o)));
}
private static bool ValidateString(JToken o)
{
return (o.Type == JTokenType.String || o.Type == JTokenType.Comment || o.Type == JTokenType.Raw || IsNullable(o));
}
private static bool ValidateBytes(JToken o)
{
return (o.Type == JTokenType.Bytes || IsNullable(o));
}
#region Cast from operators
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator bool(JToken value)
{
JValue v = EnsureValue(value);
if (v == null || !ValidateBoolean(v, false))
throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (bool)v.Value;
}
#if !PocketPC && !NET20
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator DateTimeOffset(JToken value)
{
JValue v = EnsureValue(value);
if (v == null || !ValidateDate(v, false))
throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (DateTimeOffset)v.Value;
}
#endif
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator bool?(JToken value)
{
if (value == null)
return null;
JValue v = EnsureValue(value);
if (v == null || !ValidateBoolean(v, true))
throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (bool?)v.Value;
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator long(JToken value)
{
JValue v = EnsureValue(value);
if (v == null || !ValidateInteger(v, false))
throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (long)v.Value;
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator DateTime?(JToken value)
{
if (value == null)
return null;
JValue v = EnsureValue(value);
if (v == null || !ValidateDate(v, true))
throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (DateTime?)v.Value;
}
#if !PocketPC && !NET20
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator DateTimeOffset?(JToken value)
{
if (value == null)
return null;
JValue v = EnsureValue(value);
if (v == null || !ValidateDate(v, true))
throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (DateTimeOffset?)v.Value;
}
#endif
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator decimal?(JToken value)
{
if (value == null)
return null;
JValue v = EnsureValue(value);
if (v == null || !ValidateFloat(v, true))
throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (v.Value != null) ? (decimal?)Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture) : null;
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator double?(JToken value)
{
if (value == null)
return null;
JValue v = EnsureValue(value);
if (v == null || !ValidateFloat(v, true))
throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (double?)v.Value;
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator int(JToken value)
{
JValue v = EnsureValue(value);
if (v == null || !ValidateInteger(v, false))
throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return Convert.ToInt32(v.Value, CultureInfo.InvariantCulture);
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator int?(JToken value)
{
if (value == null)
return null;
JValue v = EnsureValue(value);
if (v == null || !ValidateInteger(v, true))
throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (v.Value != null) ? (int?)Convert.ToInt32(v.Value, CultureInfo.InvariantCulture) : null;
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator DateTime(JToken value)
{
JValue v = EnsureValue(value);
if (v == null || !ValidateDate(v, false))
throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (DateTime)v.Value;
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator long?(JToken value)
{
if (value == null)
return null;
JValue v = EnsureValue(value);
if (v == null || !ValidateInteger(v, true))
throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (long?)v.Value;
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator float?(JToken value)
{
if (value == null)
return null;
JValue v = EnsureValue(value);
if (v == null || !ValidateFloat(v, true))
throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (v.Value != null) ? (float?)Convert.ToSingle(v.Value, CultureInfo.InvariantCulture) : null;
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator decimal(JToken value)
{
JValue v = EnsureValue(value);
if (v == null || !ValidateFloat(v, false))
throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture);
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator uint?(JToken value)
{
if (value == null)
return null;
JValue v = EnsureValue(value);
if (v == null || !ValidateInteger(v, true))
throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (uint?)v.Value;
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator ulong?(JToken value)
{
if (value == null)
return null;
JValue v = EnsureValue(value);
if (v == null || !ValidateInteger(v, true))
throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (ulong?)v.Value;
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator double(JToken value)
{
JValue v = EnsureValue(value);
if (v == null || !ValidateFloat(v, false))
throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (double)v.Value;
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator float(JToken value)
{
JValue v = EnsureValue(value);
if (v == null || !ValidateFloat(v, false))
throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return Convert.ToSingle(v.Value, CultureInfo.InvariantCulture);
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator string(JToken value)
{
if (value == null)
return null;
JValue v = EnsureValue(value);
if (v == null || !ValidateString(v))
throw new ArgumentException("Can not convert {0} to String.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (string)v.Value;
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator uint(JToken value)
{
JValue v = EnsureValue(value);
if (v == null || !ValidateInteger(v, false))
throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return Convert.ToUInt32(v.Value, CultureInfo.InvariantCulture);
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator ulong(JToken value)
{
JValue v = EnsureValue(value);
if (v == null || !ValidateInteger(v, false))
throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return Convert.ToUInt64(v.Value, CultureInfo.InvariantCulture);
}
///
/// Performs an explicit conversion from to .
///
/// The value.
/// The result of the conversion.
public static explicit operator byte[](JToken value)
{
JValue v = EnsureValue(value);
if (v == null || !ValidateBytes(v))
throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
return (byte[])v.Value;
}
#endregion
#region Cast to operators
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(bool value)
{
return new JValue(value);
}
#if !PocketPC && !NET20
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(DateTimeOffset value)
{
return new JValue(value);
}
#endif
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(bool? value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(long value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(DateTime? value)
{
return new JValue(value);
}
#if !PocketPC && !NET20
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(DateTimeOffset? value)
{
return new JValue(value);
}
#endif
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(decimal? value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(double? value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(ushort value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(int value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(int? value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(DateTime value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(long? value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(float? value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(decimal value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(ushort? value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(uint? value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(ulong? value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(double value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(float value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(string value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(uint value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(ulong value)
{
return new JValue(value);
}
///
/// Performs an implicit conversion from to .
///
/// The value to create a from.
/// The initialized with the specified value.
public static implicit operator JToken(byte[] value)
{
return new JValue(value);
}
#endregion
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)this).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return Children().GetEnumerator();
}
internal abstract int GetDeepHashCode();
IJEnumerable IJEnumerable.this[object key]
{
get { return this[key]; }
}
///
/// Creates an for this token.
///
/// An that can be used to read this token and its descendants.
public JsonReader CreateReader()
{
return new JTokenReader(this);
}
internal static JToken FromObjectInternal(object o, JsonSerializer jsonSerializer)
{
ValidationUtils.ArgumentNotNull(o, "o");
ValidationUtils.ArgumentNotNull(jsonSerializer, "jsonSerializer");
JToken token;
using (JTokenWriter jsonWriter = new JTokenWriter())
{
jsonSerializer.Serialize(jsonWriter, o);
token = jsonWriter.Token;
}
return token;
}
///
/// Creates a from an object.
///
/// The object that will be used to create .
/// A with the value of the specified object
public static JToken FromObject(object o)
{
return FromObjectInternal(o, new JsonSerializer());
}
///
/// Creates a from an object using the specified .
///
/// The object that will be used to create .
/// The that will be used when reading the object.
/// A with the value of the specified object
public static JToken FromObject(object o, JsonSerializer jsonSerializer)
{
return FromObjectInternal(o, jsonSerializer);
}
///
/// Creates a from a .
///
/// An positioned at the token to read into this .
///
/// An that contains the token and its descendant tokens
/// that were read from the reader. The runtime type of the token is determined
/// by the token type of the first token encountered in the reader.
///
public static JToken ReadFrom(JsonReader reader)
{
ValidationUtils.ArgumentNotNull(reader, "reader");
if (reader.TokenType == JsonToken.None)
{
if (!reader.Read())
throw new Exception("Error reading JToken from JsonReader.");
}
if (reader.TokenType == JsonToken.StartObject)
return JObject.Load(reader);
if (reader.TokenType == JsonToken.StartArray)
return JArray.Load(reader);
if (reader.TokenType == JsonToken.PropertyName)
return JProperty.Load(reader);
if (reader.TokenType == JsonToken.StartConstructor)
return JConstructor.Load(reader);
// hack. change to look at TokenType rather than using value
if (!JsonReader.IsStartToken(reader.TokenType))
return new JValue(reader.Value);
// TODO: loading constructor and parameters?
throw new Exception("Error reading JToken from JsonReader. Unexpected token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
}
internal void SetLineInfo(IJsonLineInfo lineInfo)
{
if (lineInfo == null || !lineInfo.HasLineInfo())
return;
SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition);
}
internal void SetLineInfo(int lineNumber, int linePosition)
{
_lineNumber = lineNumber;
_linePosition = linePosition;
}
bool IJsonLineInfo.HasLineInfo()
{
return (_lineNumber != null && _linePosition != null);
}
int IJsonLineInfo.LineNumber
{
get { return _lineNumber ?? 0; }
}
int IJsonLineInfo.LinePosition
{
get { return _linePosition ?? 0; }
}
///
/// Selects the token that matches the object path.
///
///
/// The object path from the current to the
/// to be returned. This must be a string of property names or array indexes separated
/// by periods, such as Tables[0].DefaultView[0].Price in C# or
/// Tables(0).DefaultView(0).Price in Visual Basic.
///
/// The that matches the object path or a null reference if no matching token is found.
public JToken SelectToken(string path)
{
return SelectToken(path, false);
}
///
/// Selects the token that matches the object path.
///
///
/// The object path from the current to the
/// to be returned. This must be a string of property names or array indexes separated
/// by periods, such as Tables[0].DefaultView[0].Price in C# or
/// Tables(0).DefaultView(0).Price in Visual Basic.
///
/// A flag to indicate whether an error should be thrown if no token is found.
/// The that matches the object path.
public JToken SelectToken(string path, bool errorWhenNoMatch)
{
JPath p = new JPath(path);
return p.Evaluate(this, errorWhenNoMatch);
}
}
}