-Add support for reading octal and hexadecimal numbers from JSON
-Fix serializing indexed properties -Fix serializing JRaw properties
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
equivalent and back again.</p>
|
||||
|
||||
|
||||
<p>For simple scenarios the <a href="./html/Overload_Newtonsoft_Json_JsonConvert_SerializeObject.htm">SerializeObject</a> and <a href="./html/Overload_Newtonsoft_Json_JsonConvert_DeserializeObject.htm">DeserializeObject</a> methods on <a href="./html/T_Newtonsoft_Json_JsonConvert.htm">JsonConvert</a> provide an easy to use wrapper over
|
||||
<p>For simple scenarios where you want to convert to and from a JSON string the <a href="./html/Overload_Newtonsoft_Json_JsonConvert_SerializeObject.htm">SerializeObject</a> and <a href="./html/Overload_Newtonsoft_Json_JsonConvert_DeserializeObject.htm">DeserializeObject</a> methods on <a href="./html/T_Newtonsoft_Json_JsonConvert.htm">JsonConvert</a> provide an easy to use wrapper over
|
||||
JsonSerializer.</p>
|
||||
|
||||
|
||||
@@ -55,8 +55,11 @@
|
||||
|
||||
|
||||
<p>For more control over how an object is serialized the JsonSerializer can be used
|
||||
directly. The JsonSerializer has a number of properties to control its behaviour
|
||||
when serializing and deserializing.</p>
|
||||
directly. The JsonSerializer is able to read and write JSON text directly to
|
||||
a stream via <a href="./html/T_Newtonsoft_Json_JsonTextReader.htm">JsonTextReader</a> and <a href="./html/T_Newtonsoft_Json_JsonTextWriter.htm">JsonTextWriter</a>. Other kinds of JsonWriters can
|
||||
also be used such as <a href="./html/T_Newtonsoft_Json_Linq_JTokenReader.htm">JTokenReader</a>/<a href="./html/T_Newtonsoft_Json_Linq_JTokenWriter.htm">JTokenWriter</a> to
|
||||
convert your object to and
|
||||
from LINQ to JSON objects or <a href="./html/T_Newtonsoft_Json_Bson_BsonReader.htm">BsonReader</a>/<a href="./html/T_Newtonsoft_Json_Bson_BsonWriter.htm">BsonWriter</a> to convert to and from BSON.</p>
|
||||
|
||||
<div class="overflowpanel"> <div class="code">
|
||||
|
||||
@@ -77,6 +80,9 @@
|
||||
</div>
|
||||
|
||||
</div></div>
|
||||
<p>JsonSerializer has a number of properties on it to customize how it serializes JSON.
|
||||
These can also be used with the methods on JsonConvert via the
|
||||
JsonSerializerSettings overloads.</p>
|
||||
|
||||
<h5>ReferenceLoopHandling</h5>
|
||||
<p>Controls how circular referencing objects are serialized. Error, ignore or
|
||||
@@ -114,11 +120,12 @@ the member's DefaultValueAttribute. Include or ignore.</p>
|
||||
<h5>XmlNodeConverter</h5>
|
||||
<p>Converts an XmlNode to and from JSON. Note that to convert a JSON object it must have only a single property
|
||||
or you must define a root node name to be inserted when using this converter. This is required because properties are converted into nodes and
|
||||
well formed XML can only have one root node.</p>
|
||||
well formed XML can only have one root node. XmlNodeConverter has an option to
|
||||
insert a root node for you.</p>
|
||||
|
||||
|
||||
<h5>BinaryConverter</h5>
|
||||
<p>Converts binary data like a byte array or SqlBinary object to JSON. The binary
|
||||
<p>Converts binary data like the SqlBinary object to JSON. The binary
|
||||
data is written as a string in JSON and is encoded in Base64.</p>
|
||||
|
||||
<h5>CustomCreationConverter</h5>
|
||||
|
||||
@@ -620,5 +620,32 @@ bye", reader.Value);
|
||||
string text = Encoding.UTF8.GetString(data, 0, data.Length);
|
||||
Assert.AreEqual("Hello world.", text);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReadOctalNumber()
|
||||
{
|
||||
StringReader s = new StringReader(@"[0372, 0xFA, 0XFA]");
|
||||
JsonTextReader jsonReader = new JsonTextReader(s);
|
||||
|
||||
Assert.IsTrue(jsonReader.Read());
|
||||
Assert.AreEqual(JsonToken.StartArray, jsonReader.TokenType);
|
||||
|
||||
Assert.IsTrue(jsonReader.Read());
|
||||
Assert.AreEqual(JsonToken.Integer, jsonReader.TokenType);
|
||||
Assert.AreEqual(250, jsonReader.Value);
|
||||
|
||||
Assert.IsTrue(jsonReader.Read());
|
||||
Assert.AreEqual(JsonToken.Integer, jsonReader.TokenType);
|
||||
Assert.AreEqual(250, jsonReader.Value);
|
||||
|
||||
Assert.IsTrue(jsonReader.Read());
|
||||
Assert.AreEqual(JsonToken.Integer, jsonReader.TokenType);
|
||||
Assert.AreEqual(250, jsonReader.Value);
|
||||
|
||||
Assert.IsTrue(jsonReader.Read());
|
||||
Assert.AreEqual(JsonToken.EndArray, jsonReader.TokenType);
|
||||
|
||||
Assert.IsFalse(jsonReader.Read());
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -2123,5 +2123,114 @@ keyword such as type of business.""
|
||||
Assert.AreEqual(1, d.List.Count);
|
||||
Assert.AreEqual("existing", d.List[0]);
|
||||
}
|
||||
|
||||
public interface IKeyValueId
|
||||
{
|
||||
int Id { get; set; }
|
||||
string Key { get; set; }
|
||||
string Value { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class KeyValueId : IKeyValueId
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Key { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class ThisGenericTest<T> where T : IKeyValueId
|
||||
{
|
||||
private Dictionary<string, T> _dict1 = new Dictionary<string, T>();
|
||||
|
||||
public string MyProperty { get; set; }
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
this._dict1.Add(item.Key, item);
|
||||
}
|
||||
|
||||
public T this[string key]
|
||||
{
|
||||
get { return this._dict1[key]; }
|
||||
set { this._dict1[key] = value; }
|
||||
}
|
||||
|
||||
public T this[int id]
|
||||
{
|
||||
get { return this._dict1.Values.FirstOrDefault(x => x.Id == id); }
|
||||
set
|
||||
{
|
||||
var item = this[id];
|
||||
|
||||
if (item == null)
|
||||
this.Add(value);
|
||||
else
|
||||
this._dict1[item.Key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string ToJson()
|
||||
{
|
||||
return JsonConvert.SerializeObject(this, Formatting.Indented);
|
||||
}
|
||||
|
||||
public T[] TheItems
|
||||
{
|
||||
get { return this._dict1.Values.ToArray<T>(); }
|
||||
set
|
||||
{
|
||||
foreach (var item in value)
|
||||
this.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IgnoreIndexedProperties()
|
||||
{
|
||||
ThisGenericTest<KeyValueId> g = new ThisGenericTest<KeyValueId>();
|
||||
|
||||
g.Add(new KeyValueId { Id = 1, Key = "key1", Value = "value1" });
|
||||
g.Add(new KeyValueId { Id = 2, Key = "key2", Value = "value2" });
|
||||
|
||||
g.MyProperty = "some value";
|
||||
|
||||
string json = g.ToJson();
|
||||
|
||||
Assert.AreEqual(@"{
|
||||
""MyProperty"": ""some value"",
|
||||
""TheItems"": [
|
||||
{
|
||||
""Id"": 1,
|
||||
""Key"": ""key1"",
|
||||
""Value"": ""value1""
|
||||
},
|
||||
{
|
||||
""Id"": 2,
|
||||
""Key"": ""key2"",
|
||||
""Value"": ""value2""
|
||||
}
|
||||
]
|
||||
}", json);
|
||||
|
||||
ThisGenericTest<KeyValueId> gen = JsonConvert.DeserializeObject<ThisGenericTest<KeyValueId>>(json);
|
||||
Assert.AreEqual("some value", gen.MyProperty);
|
||||
}
|
||||
|
||||
public class JRawValueTestObject
|
||||
{
|
||||
public JRaw Value { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void JRawValue()
|
||||
{
|
||||
JRawValueTestObject deserialized = JsonConvert.DeserializeObject<JRawValueTestObject>("{value:3}");
|
||||
Assert.AreEqual("3", deserialized.Value.ToString());
|
||||
|
||||
deserialized = JsonConvert.DeserializeObject<JRawValueTestObject>("{value:'3'}");
|
||||
Assert.AreEqual(@"""3""", deserialized.Value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -573,11 +573,6 @@ namespace Newtonsoft.Json.Converters
|
||||
{
|
||||
return c.OfType<XmlAttribute>().Where(a => a.NamespaceURI != JsonNamespaceUri);
|
||||
}
|
||||
|
||||
private IEnumerable<XmlNode> ValueNodes(XmlNodeList c)
|
||||
{
|
||||
return c.OfType<XmlNode>().Where(n => n.NamespaceURI != JsonNamespaceUri);
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -41,54 +41,39 @@ namespace Newtonsoft.Json
|
||||
/// <summary>
|
||||
/// Represents JavaScript's boolean value true as a string. This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly string True;
|
||||
public static readonly string True = "true";
|
||||
|
||||
/// <summary>
|
||||
/// Represents JavaScript's boolean value false as a string. This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly string False;
|
||||
public static readonly string False = "false";
|
||||
|
||||
/// <summary>
|
||||
/// Represents JavaScript's null as a string. This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly string Null;
|
||||
public static readonly string Null = "null";
|
||||
|
||||
/// <summary>
|
||||
/// Represents JavaScript's undefined as a string. This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly string Undefined;
|
||||
public static readonly string Undefined = "undefined";
|
||||
|
||||
/// <summary>
|
||||
/// Represents JavaScript's positive infinity as a string. This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly string PositiveInfinity;
|
||||
public static readonly string PositiveInfinity = "Infinity";
|
||||
|
||||
/// <summary>
|
||||
/// Represents JavaScript's negative infinity as a string. This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly string NegativeInfinity;
|
||||
public static readonly string NegativeInfinity = "-Infinity";
|
||||
|
||||
/// <summary>
|
||||
/// Represents JavaScript's NaN as a string. This field is read-only.
|
||||
/// </summary>
|
||||
public static readonly string NaN;
|
||||
public static readonly string NaN = "NaN";
|
||||
|
||||
internal static long InitialJavaScriptDateTicks;
|
||||
internal static DateTime MinimumJavaScriptDate;
|
||||
|
||||
static JsonConvert()
|
||||
{
|
||||
True = "true";
|
||||
False = "false";
|
||||
Null = "null";
|
||||
Undefined = "undefined";
|
||||
PositiveInfinity = "Infinity";
|
||||
NegativeInfinity = "-Infinity";
|
||||
NaN = "NaN";
|
||||
|
||||
InitialJavaScriptDateTicks = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).Ticks;
|
||||
MinimumJavaScriptDate = new DateTime(100, 1, 1);
|
||||
}
|
||||
internal static readonly long InitialJavaScriptDateTicks = 621355968000000000;
|
||||
|
||||
/// <summary>
|
||||
/// Converts the <see cref="DateTime"/> to its JSON string representation.
|
||||
@@ -409,10 +394,10 @@ namespace Newtonsoft.Json
|
||||
if (value == null)
|
||||
return Null;
|
||||
|
||||
if (value is IConvertible)
|
||||
{
|
||||
IConvertible convertible = (IConvertible)value;
|
||||
IConvertible convertible = value as IConvertible;
|
||||
|
||||
if (convertible != null)
|
||||
{
|
||||
switch (convertible.GetTypeCode())
|
||||
{
|
||||
case TypeCode.String:
|
||||
@@ -502,12 +487,10 @@ namespace Newtonsoft.Json
|
||||
if (value == null)
|
||||
return true;
|
||||
|
||||
if (value is IConvertible)
|
||||
{
|
||||
IConvertible convertible = (IConvertible)value;
|
||||
IConvertible convertible = value as IConvertible;
|
||||
|
||||
if (convertible != null)
|
||||
return IsJsonPrimitiveTypeCode(convertible.GetTypeCode());
|
||||
}
|
||||
|
||||
#if !PocketPC && !NET20
|
||||
if (value is DateTimeOffset)
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Newtonsoft.Json
|
||||
/// Instructs the <see cref="JsonSerializer"/> to use the specified <see cref="JsonConverter"/> when serializing the member or class.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = false)]
|
||||
public class JsonConverterAttribute : Attribute
|
||||
public sealed class JsonConverterAttribute : Attribute
|
||||
{
|
||||
private readonly Type _converterType;
|
||||
|
||||
|
||||
@@ -111,7 +111,6 @@ namespace Newtonsoft.Json
|
||||
protected State CurrentState
|
||||
{
|
||||
get { return _currentState; }
|
||||
private set { _currentState = value; }
|
||||
}
|
||||
|
||||
private int _top;
|
||||
@@ -172,10 +171,8 @@ namespace Newtonsoft.Json
|
||||
/// </summary>
|
||||
protected JsonReader()
|
||||
{
|
||||
//_testBuffer = new StringBuilder();
|
||||
_currentState = State.Start;
|
||||
_stack = new List<JTokenType>();
|
||||
_top = 0;
|
||||
Push(JTokenType.None);
|
||||
}
|
||||
|
||||
|
||||
@@ -663,6 +663,7 @@ namespace Newtonsoft.Json
|
||||
private void ParseNumber(char firstChar)
|
||||
{
|
||||
char currentChar = firstChar;
|
||||
bool nonBase10 = (firstChar == '0');
|
||||
|
||||
// parse until seperator character or end
|
||||
bool end = false;
|
||||
@@ -684,16 +685,23 @@ namespace Newtonsoft.Json
|
||||
object numberValue;
|
||||
JsonToken numberType;
|
||||
|
||||
if (number.IndexOf(".", StringComparison.OrdinalIgnoreCase) == -1
|
||||
&& number.IndexOf("e", StringComparison.OrdinalIgnoreCase) == -1)
|
||||
if (number.IndexOf(".", StringComparison.OrdinalIgnoreCase) != -1
|
||||
|| number.IndexOf("e", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
numberValue = Convert.ToInt64(number, CultureInfo.InvariantCulture);
|
||||
numberValue = Convert.ToDouble(number, CultureInfo.InvariantCulture);
|
||||
numberType = JsonToken.Float;
|
||||
}
|
||||
else if (nonBase10)
|
||||
{
|
||||
numberValue = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
|
||||
? Convert.ToInt64(number, 16)
|
||||
: Convert.ToInt64(number, 8);
|
||||
numberType = JsonToken.Integer;
|
||||
}
|
||||
else
|
||||
{
|
||||
numberValue = Convert.ToDouble(number, CultureInfo.InvariantCulture);
|
||||
numberType = JsonToken.Float;
|
||||
numberValue = Convert.ToInt64(number, CultureInfo.InvariantCulture);
|
||||
numberType = JsonToken.Integer;
|
||||
}
|
||||
|
||||
_buffer.Position = 0;
|
||||
|
||||
@@ -291,12 +291,7 @@ namespace Newtonsoft.Json
|
||||
if (value == null)
|
||||
WriteValueInternal(JsonConvert.Null, JsonToken.Null);
|
||||
else
|
||||
{
|
||||
JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, true);
|
||||
//_writer.Write(JavaScriptUtils.EscapeJavaScriptString(value, _quoteChar, false));
|
||||
//WriteValueInternal(, JsonToken.String);
|
||||
//JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -61,5 +61,31 @@ namespace Newtonsoft.Json.Linq
|
||||
{
|
||||
get { return new JEnumerable<JToken>(Extensions.Values<T, JToken>(_enumerable, key)); }
|
||||
}
|
||||
|
||||
/// <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 _enumerable.Equals(((JEnumerable<T>)obj)._enumerable);
|
||||
|
||||
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()
|
||||
{
|
||||
return _enumerable.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,21 +79,14 @@ namespace Newtonsoft.Json.Schema
|
||||
private JsonSchemaResolver _resolver;
|
||||
private IList<TypeSchema> _stack = new List<TypeSchema>();
|
||||
private JsonSchema _currentSchema;
|
||||
private Type _currentType;
|
||||
|
||||
private JsonSchema CurrentSchema
|
||||
{
|
||||
get { return _currentSchema; }
|
||||
}
|
||||
|
||||
private Type CurrentType
|
||||
{
|
||||
get { return _currentType; }
|
||||
}
|
||||
|
||||
private void Push(TypeSchema typeSchema)
|
||||
{
|
||||
_currentType = typeSchema.Type;
|
||||
_currentSchema = typeSchema.Schema;
|
||||
_stack.Add(typeSchema);
|
||||
_resolver.LoadedSchemas.Add(typeSchema.Schema);
|
||||
@@ -106,12 +99,10 @@ namespace Newtonsoft.Json.Schema
|
||||
TypeSchema newValue = _stack.LastOrDefault();
|
||||
if (newValue != null)
|
||||
{
|
||||
_currentType = newValue.Type;
|
||||
_currentSchema = newValue.Schema;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentType = null;
|
||||
_currentSchema = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,18 +97,22 @@ namespace Newtonsoft.Json.Serialization
|
||||
DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(objectType);
|
||||
#endif
|
||||
|
||||
List<MemberInfo> defaultMembers = ReflectionUtils.GetFieldsAndProperties(objectType, DefaultMembersSearchFlags);
|
||||
List<MemberInfo> allMembers = ReflectionUtils.GetFieldsAndProperties(objectType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
|
||||
List<MemberInfo> defaultMembers = ReflectionUtils.GetFieldsAndProperties(objectType, DefaultMembersSearchFlags)
|
||||
.Where(m => !ReflectionUtils.IsIndexedProperty(m)).ToList();
|
||||
List<MemberInfo> allMembers = ReflectionUtils.GetFieldsAndProperties(objectType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
|
||||
.Where(m => !ReflectionUtils.IsIndexedProperty(m)).ToList();
|
||||
|
||||
List<MemberInfo> serializableMembers = new List<MemberInfo>();
|
||||
foreach (MemberInfo member in allMembers)
|
||||
{
|
||||
if (defaultMembers.Contains(member))
|
||||
{
|
||||
// add all members that are found by default member search
|
||||
serializableMembers.Add(member);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add members that are explicitly marked with JsonProperty/DataMember attribute
|
||||
if (JsonTypeReflector.GetAttribute<JsonPropertyAttribute>(member) != null)
|
||||
serializableMembers.Add(member);
|
||||
#if !PocketPC && !NET20
|
||||
@@ -323,6 +327,11 @@ namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
return CreateObjectContract(objectType);
|
||||
}
|
||||
if (objectType.IsSubclassOf(typeof(JToken)))
|
||||
{
|
||||
return CreateLinqContract(objectType);
|
||||
}
|
||||
|
||||
if (CollectionUtils.IsDictionaryType(objectType))
|
||||
{
|
||||
return CreateDictionaryContract(objectType);
|
||||
@@ -331,10 +340,6 @@ namespace Newtonsoft.Json.Serialization
|
||||
{
|
||||
return CreateArrayContract(objectType);
|
||||
}
|
||||
if (objectType.IsSubclassOf(typeof(JToken)))
|
||||
{
|
||||
return CreateLinqContract(objectType);
|
||||
}
|
||||
|
||||
return CreateObjectContract(objectType);
|
||||
}
|
||||
|
||||
@@ -550,9 +550,15 @@ namespace Newtonsoft.Json.Utilities
|
||||
foreach (var groupedMember in groupedMembers)
|
||||
{
|
||||
if (groupedMember.Count == 1)
|
||||
{
|
||||
distinctMembers.Add(groupedMember.Members.First());
|
||||
}
|
||||
else
|
||||
distinctMembers.Add(groupedMember.Members.Where(m => !IsOverridenGenericMember(m, bindingAttr)).First());
|
||||
{
|
||||
var members = groupedMember.Members.Where(m => !IsOverridenGenericMember(m, bindingAttr) || m.Name == "Item");
|
||||
|
||||
distinctMembers.AddRange(members);
|
||||
}
|
||||
}
|
||||
|
||||
return distinctMembers;
|
||||
|
||||
Reference in New Issue
Block a user