#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.IO; using System.Globalization; using Newtonsoft.Json.Utilities; using System.Xml; using Newtonsoft.Json.Converters; using System.Text; #if !NET20 && !SILVERLIGHT using System.Xml.Linq; #endif namespace Newtonsoft.Json { /// /// Provides methods for converting between common language runtime types and JSON types. /// public static class JsonConvert { /// /// Represents JavaScript's boolean value true as a string. This field is read-only. /// public static readonly string True = "true"; /// /// Represents JavaScript's boolean value false as a string. This field is read-only. /// public static readonly string False = "false"; /// /// Represents JavaScript's null as a string. This field is read-only. /// public static readonly string Null = "null"; /// /// Represents JavaScript's undefined as a string. This field is read-only. /// public static readonly string Undefined = "undefined"; /// /// Represents JavaScript's positive infinity as a string. This field is read-only. /// public static readonly string PositiveInfinity = "Infinity"; /// /// Represents JavaScript's negative infinity as a string. This field is read-only. /// public static readonly string NegativeInfinity = "-Infinity"; /// /// Represents JavaScript's NaN as a string. This field is read-only. /// public static readonly string NaN = "NaN"; internal static readonly long InitialJavaScriptDateTicks = 621355968000000000; /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(DateTime value) { using (StringWriter writer = StringUtils.CreateStringWriter(64)) { WriteDateTimeString(writer, value, GetUtcOffset(value), value.Kind); return writer.ToString(); } } #if !PocketPC && !NET20 /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(DateTimeOffset value) { using (StringWriter writer = StringUtils.CreateStringWriter(64)) { WriteDateTimeString(writer, value.UtcDateTime, value.Offset, DateTimeKind.Local); return writer.ToString(); } } #endif private static TimeSpan GetUtcOffset(DateTime dateTime) { #if SILVERLIGHT return TimeZoneInfo.Local.GetUtcOffset(dateTime); #else return TimeZone.CurrentTimeZone.GetUtcOffset(dateTime); #endif } internal static void WriteDateTimeString(TextWriter writer, DateTime value) { WriteDateTimeString(writer, value, GetUtcOffset(value), value.Kind); } internal static void WriteDateTimeString(TextWriter writer, DateTime value, TimeSpan offset, DateTimeKind kind) { long javaScriptTicks = ConvertDateTimeToJavaScriptTicks(value, offset); writer.Write(@"""\/Date("); writer.Write(javaScriptTicks); switch (kind) { case DateTimeKind.Local: case DateTimeKind.Unspecified: writer.Write((offset.Ticks >= 0L) ? "+" : "-"); int absHours = Math.Abs(offset.Hours); if (absHours < 10) writer.Write(0); writer.Write(absHours); int absMinutes = Math.Abs(offset.Minutes); if (absMinutes < 10) writer.Write(0); writer.Write(absMinutes); break; } writer.Write(@")\/"""); } private static long ToUniversalTicks(DateTime dateTime) { if (dateTime.Kind == DateTimeKind.Utc) return dateTime.Ticks; return ToUniversalTicks(dateTime, GetUtcOffset(dateTime)); } private static long ToUniversalTicks(DateTime dateTime, TimeSpan offset) { if (dateTime.Kind == DateTimeKind.Utc) return dateTime.Ticks; long ticks = dateTime.Ticks - offset.Ticks; if (ticks > 3155378975999999999L) return 3155378975999999999L; if (ticks < 0L) return 0L; return ticks; } internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, TimeSpan offset) { long universialTicks = ToUniversalTicks(dateTime, offset); return UniversialTicksToJavaScriptTicks(universialTicks); } internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime) { long universialTicks = ToUniversalTicks(dateTime); return UniversialTicksToJavaScriptTicks(universialTicks); } private static long UniversialTicksToJavaScriptTicks(long universialTicks) { long javaScriptTicks = (universialTicks - InitialJavaScriptDateTicks) / 10000; return javaScriptTicks; } internal static DateTime ConvertJavaScriptTicksToDateTime(long javaScriptTicks) { DateTime dateTime = new DateTime((javaScriptTicks * 10000) + InitialJavaScriptDateTicks, DateTimeKind.Utc); return dateTime; } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(bool value) { return (value) ? True : False; } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(char value) { return ToString(char.ToString(value)); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(Enum value) { return value.ToString("D"); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(int value) { return value.ToString(null, CultureInfo.InvariantCulture); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(short value) { return value.ToString(null, CultureInfo.InvariantCulture); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(ushort value) { return value.ToString(null, CultureInfo.InvariantCulture); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(uint value) { return value.ToString(null, CultureInfo.InvariantCulture); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(long value) { return value.ToString(null, CultureInfo.InvariantCulture); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(ulong value) { return value.ToString(null, CultureInfo.InvariantCulture); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(float value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(double value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } private static string EnsureDecimalPlace(double value, string text) { if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1) return text; return text + ".0"; } private static string EnsureDecimalPlace(string text) { if (text.IndexOf('.') != -1) return text; return text + ".0"; } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(byte value) { return value.ToString(null, CultureInfo.InvariantCulture); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(sbyte value) { return value.ToString(null, CultureInfo.InvariantCulture); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(decimal value) { return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture)); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(Guid value) { return '"' + value.ToString("D", CultureInfo.InvariantCulture) + '"'; } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(string value) { return ToString(value, '"'); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// The string delimiter character. /// A JSON string representation of the . public static string ToString(string value, char delimter) { return JavaScriptUtils.ToEscapedJavaScriptString(value, delimter, true); } /// /// Converts the to its JSON string representation. /// /// The value to convert. /// A JSON string representation of the . public static string ToString(object value) { if (value == null) return Null; IConvertible convertible = value as IConvertible; if (convertible != null) { switch (convertible.GetTypeCode()) { case TypeCode.String: return ToString(convertible.ToString(CultureInfo.InvariantCulture)); case TypeCode.Char: return ToString(convertible.ToChar(CultureInfo.InvariantCulture)); case TypeCode.Boolean: return ToString(convertible.ToBoolean(CultureInfo.InvariantCulture)); case TypeCode.SByte: return ToString(convertible.ToSByte(CultureInfo.InvariantCulture)); case TypeCode.Int16: return ToString(convertible.ToInt16(CultureInfo.InvariantCulture)); case TypeCode.UInt16: return ToString(convertible.ToUInt16(CultureInfo.InvariantCulture)); case TypeCode.Int32: return ToString(convertible.ToInt32(CultureInfo.InvariantCulture)); case TypeCode.Byte: return ToString(convertible.ToByte(CultureInfo.InvariantCulture)); case TypeCode.UInt32: return ToString(convertible.ToUInt32(CultureInfo.InvariantCulture)); case TypeCode.Int64: return ToString(convertible.ToInt64(CultureInfo.InvariantCulture)); case TypeCode.UInt64: return ToString(convertible.ToUInt64(CultureInfo.InvariantCulture)); case TypeCode.Single: return ToString(convertible.ToSingle(CultureInfo.InvariantCulture)); case TypeCode.Double: return ToString(convertible.ToDouble(CultureInfo.InvariantCulture)); case TypeCode.DateTime: return ToString(convertible.ToDateTime(CultureInfo.InvariantCulture)); case TypeCode.Decimal: return ToString(convertible.ToDecimal(CultureInfo.InvariantCulture)); case TypeCode.DBNull: return Null; } } #if !PocketPC && !NET20 else if (value is DateTimeOffset) { return ToString((DateTimeOffset)value); } #endif throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } private static bool IsJsonPrimitiveTypeCode(TypeCode typeCode) { switch (typeCode) { case TypeCode.String: case TypeCode.Char: case TypeCode.Boolean: case TypeCode.SByte: case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Int32: case TypeCode.Byte: case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Single: case TypeCode.Double: case TypeCode.DateTime: case TypeCode.Decimal: case TypeCode.DBNull: return true; default: return false; } } internal static bool IsJsonPrimitiveType(Type type) { if (ReflectionUtils.IsNullableType(type)) type = Nullable.GetUnderlyingType(type); #if !PocketPC && !NET20 if (type == typeof(DateTimeOffset)) return true; #endif if (type == typeof(byte[])) return true; return IsJsonPrimitiveTypeCode(Type.GetTypeCode(type)); } internal static bool IsJsonPrimitive(object value) { if (value == null) return true; IConvertible convertible = value as IConvertible; if (convertible != null) return IsJsonPrimitiveTypeCode(convertible.GetTypeCode()); #if !PocketPC && !NET20 if (value is DateTimeOffset) return true; #endif if (value is byte[]) return true; return false; } /// /// Serializes the specified object to a JSON string. /// /// The object to serialize. /// A JSON string representation of the object. public static string SerializeObject(object value) { return SerializeObject(value, Formatting.None, (JsonSerializerSettings)null); } /// /// Serializes the specified object to a JSON string. /// /// The object to serialize. /// Indicates how the output is formatted. /// /// A JSON string representation of the object. /// public static string SerializeObject(object value, Formatting formatting) { return SerializeObject(value, formatting, (JsonSerializerSettings)null); } /// /// Serializes the specified object to a JSON string using a collection of . /// /// The object to serialize. /// A collection converters used while serializing. /// A JSON string representation of the object. public static string SerializeObject(object value, params JsonConverter[] converters) { return SerializeObject(value, Formatting.None, converters); } /// /// Serializes the specified object to a JSON string using a collection of . /// /// The object to serialize. /// Indicates how the output is formatted. /// A collection converters used while serializing. /// A JSON string representation of the object. public static string SerializeObject(object value, Formatting formatting, params JsonConverter[] converters) { JsonSerializerSettings settings = (converters != null && converters.Length > 0) ? new JsonSerializerSettings { Converters = converters } : null; return SerializeObject(value, formatting, settings); } /// /// Serializes the specified object to a JSON string using a collection of . /// /// The object to serialize. /// Indicates how the output is formatted. /// The used to serialize the object. /// If this is null, default serialization settings will be is used. /// /// A JSON string representation of the object. /// public static string SerializeObject(object value, Formatting formatting, JsonSerializerSettings settings) { JsonSerializer jsonSerializer = JsonSerializer.Create(settings); StringBuilder sb = new StringBuilder(128); StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture); using (JsonTextWriter jsonWriter = new JsonTextWriter(sw)) { jsonWriter.Formatting = formatting; jsonSerializer.Serialize(jsonWriter, value); } return sw.ToString(); } /// /// Deserializes the specified object to a Json object. /// /// The object to deserialize. /// The deserialized object from the Json string. public static object DeserializeObject(string value) { return DeserializeObject(value, null, (JsonSerializerSettings)null); } /// /// Deserializes the specified object to a Json object. /// /// The object to deserialize. /// The of object being deserialized. /// The deserialized object from the Json string. public static object DeserializeObject(string value, Type type) { return DeserializeObject(value, type, (JsonSerializerSettings)null); } /// /// Deserializes the specified object to a Json object. /// /// The type of the object to deserialize. /// The object to deserialize. /// The deserialized object from the Json string. public static T DeserializeObject(string value) { return DeserializeObject(value, (JsonSerializerSettings)null); } /// /// Deserializes the specified JSON to the given anonymous type. /// /// /// The anonymous type to deserialize to. This can't be specified /// traditionally and must be infered from the anonymous type passed /// as a parameter. /// /// The object to deserialize. /// The anonymous type object. /// The deserialized anonymous type from the JSON string. public static T DeserializeAnonymousType(string value, T anonymousTypeObject) { return DeserializeObject(value); } /// /// Deserializes the JSON string to the specified type. /// /// The type of the object to deserialize. /// The object to deserialize. /// Converters to use while deserializing. /// The deserialized object from the JSON string. public static T DeserializeObject(string value, params JsonConverter[] converters) { return (T)DeserializeObject(value, typeof(T), converters); } /// /// Deserializes the JSON string to the specified type. /// /// The type of the object to deserialize. /// The object to deserialize. /// /// The used to deserialize the object. /// If this is null, default serialization settings will be is used. /// /// The deserialized object from the JSON string. public static T DeserializeObject(string value, JsonSerializerSettings settings) { return (T)DeserializeObject(value, typeof(T), settings); } /// /// Deserializes the JSON string to the specified type. /// /// The object to deserialize. /// The type of the object to deserialize. /// Converters to use while deserializing. /// The deserialized object from the JSON string. public static object DeserializeObject(string value, Type type, params JsonConverter[] converters) { JsonSerializerSettings settings = (converters != null && converters.Length > 0) ? new JsonSerializerSettings { Converters = converters } : null; return DeserializeObject(value, type, settings); } /// /// Deserializes the JSON string to the specified type. /// /// The JSON to deserialize. /// The type of the object to deserialize. /// /// The used to deserialize the object. /// If this is null, default serialization settings will be is used. /// /// The deserialized object from the JSON string. public static object DeserializeObject(string value, Type type, JsonSerializerSettings settings) { StringReader sr = new StringReader(value); JsonSerializer jsonSerializer = JsonSerializer.Create(settings); object deserializedValue; using (JsonReader jsonReader = new JsonTextReader(sr)) { deserializedValue = jsonSerializer.Deserialize(jsonReader, type); if (jsonReader.Read() && jsonReader.TokenType != JsonToken.Comment) throw new JsonSerializationException("Additional text found in JSON string after finishing deserializing object."); } return deserializedValue; } /// /// Populates the object with values from the JSON string. /// /// The JSON to populate values from. /// The target object to populate values onto. public static void PopulateObject(string value, object target) { PopulateObject(value, target, null); } /// /// Populates the object with values from the JSON string. /// /// The JSON to populate values from. /// The target object to populate values onto. /// /// The used to deserialize the object. /// If this is null, default serialization settings will be is used. /// public static void PopulateObject(string value, object target, JsonSerializerSettings settings) { StringReader sr = new StringReader(value); JsonSerializer jsonSerializer = JsonSerializer.Create(settings); using (JsonReader jsonReader = new JsonTextReader(sr)) { jsonSerializer.Populate(jsonReader, target); if (jsonReader.Read() && jsonReader.TokenType != JsonToken.Comment) throw new JsonSerializationException("Additional text found in JSON string after finishing deserializing object."); } } #if !NET20 && !SILVERLIGHT /// /// Serializes the to a JSON string. /// /// The node to convert to JSON. /// A JSON string of the XNode. public static string SerializeXNode(XObject node) { return SerializeXNode(node, Formatting.None); } /// /// Serializes the to a JSON string. /// /// The node to convert to JSON. /// Indicates how the output is formatted. /// A JSON string of the XNode. public static string SerializeXNode(XObject node, Formatting formatting) { XmlNodeConverter converter = new XmlNodeConverter(); return SerializeObject(node, formatting, converter); } /// /// Deserializes the from a JSON string. /// /// The JSON string. /// The deserialized XNode public static XDocument DeserializeXNode(string value) { return DeserializeXNode(value, null); } /// /// Deserializes the from a JSON string nested in a root elment. /// /// The JSON string. /// The name of the root element to append when deserializing. /// The deserialized XNode public static XDocument DeserializeXNode(string value, string deserializeRootElementName) { XmlNodeConverter converter = new XmlNodeConverter(); converter.DeserializeRootElementName = deserializeRootElementName; return (XDocument)DeserializeObject(value, typeof(XDocument), converter); } #endif #if !SILVERLIGHT /// /// Serializes the XML node to a JSON string. /// /// The node to serialize. /// A JSON string of the XmlNode. public static string SerializeXmlNode(XmlNode node) { return SerializeXmlNode(node, Formatting.None); } /// /// Serializes the XML node to a JSON string. /// /// The node to serialize. /// Indicates how the output is formatted. /// A JSON string of the XmlNode. public static string SerializeXmlNode(XmlNode node, Formatting formatting) { XmlNodeConverter converter = new XmlNodeConverter(); return SerializeObject(node, formatting, converter); } /// /// Deserializes the XmlNode from a JSON string. /// /// The JSON string. /// The deserialized XmlNode public static XmlDocument DeserializeXmlNode(string value) { return DeserializeXmlNode(value, null); } /// /// Deserializes the XmlNode from a JSON string nested in a root elment. /// /// The JSON string. /// The name of the root element to append when deserializing. /// The deserialized XmlNode public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName) { XmlNodeConverter converter = new XmlNodeConverter(); converter.DeserializeRootElementName = deserializeRootElementName; return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), converter); } #endif } }