Code:
/ DotNET / DotNET / 8.0 / untmp / Orcas / RTM / ndp / fx / src / xsp / System / Web / Extensions / Script / Serialization / JavaScriptSerializer.cs / 1 / JavaScriptSerializer.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Web.Script.Serialization { using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; using System.Security.Permissions; using System.Text; using System.Web; using System.Web.Resources; [ AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal), AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal) ] public class JavaScriptSerializer { internal const string ServerTypeFieldName = "__type"; internal const int DefaultRecursionLimit = 100; internal const int DefaultMaxJsonLength = 2097152; internal static JavaScriptSerializer CreateInstance() { return CreateInstance(null); } internal static JavaScriptSerializer CreateInstance(JavaScriptTypeResolver resolver) { #pragma warning disable 618 return new JavaScriptSerializer(resolver); #pragma warning restore 618 } internal static string SerializeInternal(object o) { JavaScriptSerializer serializer = JavaScriptSerializer.CreateInstance(); return serializer.Serialize(o); } internal static object Deserialize(JavaScriptSerializer serializer, string input, Type type, int depthLimit) { if (input == null) { throw new ArgumentNullException("input"); } if (input.Length > serializer.MaxJsonLength) { throw new ArgumentException(AtlasWeb.JSON_MaxJsonLengthExceeded, "input"); } object o = JavaScriptObjectDeserializer.BasicDeserialize(input, depthLimit, serializer); return ObjectConverter.ConvertObjectToType(o, type, serializer); } // INSTANCE fields/methods private JavaScriptTypeResolver _typeResolver; private int _recursionLimit; private int _maxJsonLength; [Obsolete("The recommended alternative is System.Runtime.Serialization.DataContractJsonSerializer.")] public JavaScriptSerializer() : this(null) { } [Obsolete("The recommended alternative is System.Runtime.Serialization.DataContractJsonSerializer.")] public JavaScriptSerializer(JavaScriptTypeResolver resolver) { _typeResolver = resolver; RecursionLimit = DefaultRecursionLimit; MaxJsonLength = DefaultMaxJsonLength; } public int MaxJsonLength { get { return _maxJsonLength; } set { if (value < 1) { throw new ArgumentOutOfRangeException(AtlasWeb.JSON_InvalidMaxJsonLength); } _maxJsonLength = value; } } public int RecursionLimit { get { return _recursionLimit; } set { if (value < 1) { throw new ArgumentOutOfRangeException(AtlasWeb.JSON_InvalidRecursionLimit); } _recursionLimit = value; } } internal JavaScriptTypeResolver TypeResolver { get { return _typeResolver; } } private Dictionary_converters; private Dictionary Converters { get { if (_converters == null) { _converters = new Dictionary (); } return _converters; } } public void RegisterConverters(IEnumerable converters) { if (converters == null) { throw new ArgumentNullException("converters"); } foreach (JavaScriptConverter converter in converters) { IEnumerable supportedTypes = converter.SupportedTypes; if (supportedTypes != null) { foreach (Type supportedType in supportedTypes) { Converters[supportedType] = converter; } } } } private JavaScriptConverter GetConverter(Type t) { if (_converters != null) { while (t != null) { if (_converters.ContainsKey(t)) { return _converters[t]; } t = t.BaseType; } } return null; } internal bool ConverterExistsForType(Type t, out JavaScriptConverter converter) { converter = GetConverter(t); return converter != null; } public object DeserializeObject(string input) { return Deserialize(this, input, null /*type*/, RecursionLimit); } [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Generic parameter is preferable to forcing caller to downcast. " + "Has has been approved by API review board.")] public T Deserialize (string input) { return (T)Deserialize(this, input, typeof(T), RecursionLimit); } [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Generic parameter is preferable to forcing caller to downcast. " + "Has has been approved by API review board.")] public T ConvertToType (object obj) { return (T)ObjectConverter.ConvertObjectToType(obj, typeof(T), this); } public string Serialize(object obj) { return Serialize(obj, SerializationFormat.JSON); } private string Serialize(object obj, SerializationFormat serializationFormat) { StringBuilder sb = new StringBuilder(); Serialize(obj, sb, serializationFormat); return sb.ToString(); } public void Serialize(object obj, StringBuilder output) { Serialize(obj, output, SerializationFormat.JSON); } internal void Serialize(object obj, StringBuilder output, SerializationFormat serializationFormat) { SerializeValue(obj, output, 0, null, serializationFormat); // DevDiv Bugs 96574: Max JSON length does not apply when serializing to Javascript for ScriptDescriptors if (serializationFormat == SerializationFormat.JSON && output.Length > MaxJsonLength) { throw new InvalidOperationException(AtlasWeb.JSON_MaxJsonLengthExceeded); } } private static void SerializeBoolean(bool o, StringBuilder sb) { if (o) { sb.Append("true"); } else { sb.Append("false"); } } private static void SerializeUri(Uri uri, StringBuilder sb) { sb.Append("\"").Append(uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped)).Append("\""); } private static void SerializeGuid(Guid guid, StringBuilder sb) { sb.Append("\"").Append(guid.ToString()).Append("\""); } internal static readonly long DatetimeMinTimeTicks = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).Ticks; private static void SerializeDateTime(DateTime datetime, StringBuilder sb, SerializationFormat serializationFormat) { Debug.Assert(serializationFormat == SerializationFormat.JSON || serializationFormat == SerializationFormat.JavaScript); if (serializationFormat == SerializationFormat.JSON) { // DevDiv 41127: Never confuse atlas serialized strings with dates // Serialized date: "\/Date(123)\/" sb.Append(@"""\/Date("); sb.Append((datetime.ToUniversalTime().Ticks - DatetimeMinTimeTicks) / 10000); sb.Append(@")\/"""); } else { // DevDiv 96574: Need to be able to serialize to javascript dates for script descriptors // new Date(ticks) sb.Append("new Date("); sb.Append((datetime.ToUniversalTime().Ticks - DatetimeMinTimeTicks) / 10000); sb.Append(@")"); } } // Serialize custom object graph private void SerializeCustomObject(object o, StringBuilder sb, int depth, Hashtable objectsInUse, SerializationFormat serializationFormat) { bool first = true; Type type = o.GetType(); sb.Append('{'); // Serialize the object type if we have a type resolver if (TypeResolver != null) { // Only do this if the context is actually aware of this type string typeString = TypeResolver.ResolveTypeId(type); if (typeString != null) { SerializeString(ServerTypeFieldName, sb); sb.Append(':'); SerializeValue(typeString, sb, depth, objectsInUse, serializationFormat); first = false; } } FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo fieldInfo in fields) { // Ignore all fields marked as [ScriptIgnore] if (fieldInfo.IsDefined(typeof(ScriptIgnoreAttribute), true /*inherits*/)) continue; if (!first) sb.Append(','); SerializeString(fieldInfo.Name, sb); sb.Append(':'); SerializeValue(fieldInfo.GetValue(o), sb, depth, objectsInUse, serializationFormat); first = false; } PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty); foreach (PropertyInfo propInfo in props) { // Ignore all properties marked as [ScriptIgnore] if (propInfo.IsDefined(typeof(ScriptIgnoreAttribute), true /*inherits*/)) continue; MethodInfo getMethodInfo = propInfo.GetGetMethod(); // Skip property if it has no get if (getMethodInfo == null) { continue; } // Ignore indexed properties if (getMethodInfo.GetParameters().Length > 0) continue; if (!first) sb.Append(','); SerializeString(propInfo.Name, sb); sb.Append(':'); SerializeValue(getMethodInfo.Invoke(o, null), sb, depth, objectsInUse, serializationFormat); first = false; } sb.Append('}'); } private void SerializeDictionary(IDictionary o, StringBuilder sb, int depth, Hashtable objectsInUse, SerializationFormat serializationFormat) { sb.Append('{'); bool isFirstElement = true; bool isTypeEntrySet = false; //make sure __type field is the first to be serialized if it exists if (o.Contains(ServerTypeFieldName)) { isFirstElement = false; isTypeEntrySet = true; SerializeDictionaryKeyValue(ServerTypeFieldName, o[ServerTypeFieldName], sb, depth, objectsInUse, serializationFormat); } foreach (DictionaryEntry entry in (IDictionary)o) { string key = entry.Key as string; if (key == null) { throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, AtlasWeb.JSON_DictionaryTypeNotSupported, o.GetType().FullName)); } if (isTypeEntrySet && String.Equals(key, ServerTypeFieldName, StringComparison.Ordinal)) { // The dictionay only contains max one entry for __type key, and it has been iterated // through, so don't need to check for is anymore. isTypeEntrySet = false; continue; } if (!isFirstElement) { sb.Append(','); } SerializeDictionaryKeyValue(key, entry.Value, sb, depth, objectsInUse, serializationFormat); isFirstElement = false; } sb.Append('}'); } private void SerializeDictionaryKeyValue(string key, object value, StringBuilder sb, int depth, Hashtable objectsInUse, SerializationFormat serializationFormat) { SerializeString(key, sb); sb.Append(':'); SerializeValue(value, sb, depth, objectsInUse, serializationFormat); } private void SerializeEnumerable(IEnumerable enumerable, StringBuilder sb, int depth, Hashtable objectsInUse, SerializationFormat serializationFormat) { sb.Append('['); bool isFirstElement = true; foreach (object o in enumerable) { if (!isFirstElement) { sb.Append(','); } SerializeValue(o, sb, depth, objectsInUse, serializationFormat); isFirstElement = false; } sb.Append(']'); } private static void SerializeString(string input, StringBuilder sb) { sb.Append('"'); sb.Append(JavaScriptString.QuoteString(input)); sb.Append('"'); } private void SerializeValue(object o, StringBuilder sb, int depth, Hashtable objectsInUse, SerializationFormat serializationFormat) { if (++depth > _recursionLimit) { throw new ArgumentException(AtlasWeb.JSON_DepthLimitExceeded); } // Check whether a custom converter is available for this type. JavaScriptConverter converter = null; if (o != null && ConverterExistsForType(o.GetType(), out converter)) { IDictionary dict = converter.Serialize(o, this); if (TypeResolver != null) { string typeString = TypeResolver.ResolveTypeId(o.GetType()); if (typeString != null) { dict[ServerTypeFieldName] = typeString; } } sb.Append(Serialize(dict, serializationFormat)); return; } SerializeValueInternal(o, sb, depth, objectsInUse, serializationFormat); } // We use this for our cycle detection for the case where objects override equals/gethashcode private class ReferenceComparer : IEqualityComparer { bool IEqualityComparer.Equals(object x, object y) { return x == y; } int IEqualityComparer.GetHashCode(object obj) { return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj); } } private void SerializeValueInternal(object o, StringBuilder sb, int depth, Hashtable objectsInUse, SerializationFormat serializationFormat) { // 'null' is a special JavaScript token if (o == null || DBNull.Value.Equals(o)) { sb.Append("null"); return; } // Strings and chars are represented as quoted (single or double) in Javascript. string os = o as String; if (os != null) { SerializeString(os, sb); return; } if (o is Char) { // Special case the null char as we don't want it to turn into a null string if ((char)o == '\0') { sb.Append("null"); return; } SerializeString(o.ToString(), sb); return; } // Bools are represented as 'true' and 'false' (no quotes) in Javascript. if (o is bool) { SerializeBoolean((bool)o, sb); return; } if (o is DateTime) { SerializeDateTime((DateTime)o, sb, serializationFormat); return; } if (o is Guid) { SerializeGuid((Guid)o, sb); return; } Uri uri = o as Uri; if (uri != null) { SerializeUri(uri, sb); return; } // Have to special case floats to get full precision if (o is double) { sb.Append(((double)o).ToString("r", CultureInfo.InvariantCulture)); return; } if (o is float) { sb.Append(((float)o).ToString("r", CultureInfo.InvariantCulture)); return; } // Deal with any server type that can be represented as a number in JavaScript if (o.GetType().IsPrimitive || o is Decimal) { IConvertible convertible = o as IConvertible; if (convertible != null) { sb.Append(convertible.ToString(CultureInfo.InvariantCulture)); } else { // In theory, all primitive types implement IConvertible Debug.Assert(false); sb.Append(o.ToString()); } return; } // Serialize enums as their integer value Type type = o.GetType(); if (type.IsEnum) { sb.Append((int)o); return; } try { // The following logic performs circular reference detection if (objectsInUse == null) { // Create the table on demand objectsInUse = new Hashtable(new ReferenceComparer()); } else if (objectsInUse.ContainsKey(o)) { // If the object is already there, we have a circular reference! throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, AtlasWeb.JSON_CircularReference, type.FullName)); } // Add the object to the objectsInUse objectsInUse.Add(o, null); // Dictionaries are represented as Javascript objects. e.g. { name1: val1, name2: val2 } IDictionary od = o as IDictionary; if (od != null) { SerializeDictionary(od, sb, depth, objectsInUse, serializationFormat); return; } // Enumerations are represented as Javascript arrays. e.g. [ val1, val2 ] IEnumerable oenum = o as IEnumerable; if (oenum != null) { SerializeEnumerable(oenum, sb, depth, objectsInUse, serializationFormat); return; } // Serialize all public fields and properties. SerializeCustomObject(o, sb, depth, objectsInUse, serializationFormat); } finally { // Remove the object from the circular reference detection table if (objectsInUse != null) { objectsInUse.Remove(o); } } } internal enum SerializationFormat { JSON, JavaScript } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- StylusPointDescription.cs
- BitmapEffect.cs
- ObjectStorage.cs
- ControlParameter.cs
- TextTreeNode.cs
- DiffuseMaterial.cs
- Authorization.cs
- Vector3D.cs
- RuleSettingsCollection.cs
- TrackBar.cs
- HtmlTableCellCollection.cs
- NumberSubstitution.cs
- Row.cs
- HMACMD5.cs
- HttpModuleAction.cs
- ActivityUtilities.cs
- Vector3DAnimationUsingKeyFrames.cs
- WebReferencesBuildProvider.cs
- ListBoxAutomationPeer.cs
- KeyValuePair.cs
- WebPartDisplayModeCancelEventArgs.cs
- Optimizer.cs
- UpdatableGenericsFeature.cs
- ContentTypeSettingClientMessageFormatter.cs
- PropertyCollection.cs
- AssemblyBuilder.cs
- EventSourceCreationData.cs
- FocusManager.cs
- ListBoxChrome.cs
- WorkflowTerminatedException.cs
- DataServiceQueryOfT.cs
- RouteParameter.cs
- JoinTreeNode.cs
- RegexCharClass.cs
- RuleAction.cs
- BaseEntityWrapper.cs
- Parallel.cs
- SapiRecognizer.cs
- Attributes.cs
- MatrixConverter.cs
- DBAsyncResult.cs
- MainMenu.cs
- DataGridViewRowPostPaintEventArgs.cs
- EndOfStreamException.cs
- PartBasedPackageProperties.cs
- RtfToken.cs
- SqlXml.cs
- Item.cs
- LinqDataSourceDeleteEventArgs.cs
- TemplateManager.cs
- Quaternion.cs
- PixelFormats.cs
- categoryentry.cs
- TemplatingOptionsDialog.cs
- XmlElementAttributes.cs
- TableLayoutCellPaintEventArgs.cs
- SwitchElementsCollection.cs
- SqlRecordBuffer.cs
- SqlCachedBuffer.cs
- RC2CryptoServiceProvider.cs
- DictionaryEntry.cs
- HMAC.cs
- ReachObjectContext.cs
- SettingsBase.cs
- ErrorFormatter.cs
- ListItemCollection.cs
- UserPrincipalNameElement.cs
- BitmapCodecInfo.cs
- Baml2006ReaderFrame.cs
- ConnectionPointGlyph.cs
- ReferencedType.cs
- diagnosticsswitches.cs
- CodeObject.cs
- ResourcePool.cs
- TrustLevel.cs
- SafePointer.cs
- ParallelRangeManager.cs
- WindowsScrollBar.cs
- Drawing.cs
- AnnotationService.cs
- ShapingEngine.cs
- DefaultTextStoreTextComposition.cs
- AttributeEmitter.cs
- PtsCache.cs
- XmlWhitespace.cs
- ToolTip.cs
- RijndaelManaged.cs
- EditingScope.cs
- GridViewHeaderRowPresenter.cs
- InvalidAsynchronousStateException.cs
- WebPartDescriptionCollection.cs
- GifBitmapDecoder.cs
- TextContainerHelper.cs
- Int32Rect.cs
- DesignSurfaceServiceContainer.cs
- BasicHttpSecurityMode.cs
- Operator.cs
- Bits.cs
- wmiutil.cs
- InkSerializer.cs