Author: atsushi
Date: 2008-01-24 05:14:47 -0500 (Thu, 24 Jan 2008)
New Revision: 93778

Added:
   
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs
Modified:
   
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/ChangeLog
   
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs
   
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/TypeMap.cs
   trunk/olive/class/System.ServiceModel.Web/System.ServiceModel.Web.dll.sources
   
trunk/olive/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/ChangeLog
   
trunk/olive/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs
Log:
2008-01-24  Atsushi Enomoto  <[EMAIL PROTECTED]>

        * JsonSerializationReader.cs : new, for JSON deserialization support.
        * DataContractJsonSerializer.cs, TypeMap.cs :
          basic support for deserialization.

        * DataContractJsonSerializerTest.cs : some more deserialization tests.



Modified: 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/ChangeLog
===================================================================
--- 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/ChangeLog
       2008-01-24 10:00:01 UTC (rev 93777)
+++ 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/ChangeLog
       2008-01-24 10:14:47 UTC (rev 93778)
@@ -1,5 +1,11 @@
 2008-01-24  Atsushi Enomoto  <[EMAIL PROTECTED]>
 
+       * JsonSerializationReader.cs : new, for JSON deserialization support.
+       * DataContractJsonSerializer.cs, TypeMap.cs :
+         basic support for deserialization.
+
+2008-01-24  Atsushi Enomoto  <[EMAIL PROTECTED]>
+
        * DataContractJsonSerializer.cs,
          TypeMap.cs,
          JsonSerializationWriter.cs : split the first to those three files.

Modified: 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs
===================================================================
--- 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs
   2008-01-24 10:00:01 UTC (rev 93777)
+++ 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs
   2008-01-24 10:14:47 UTC (rev 93778)
@@ -78,7 +78,6 @@
                {
                }
 
-               [MonoTODO]
                public DataContractJsonSerializer (Type type, string rootName, 
IEnumerable<Type> knownTypes, int maxItemsInObjectGraph, bool 
ignoreExtensionDataObject, IDataContractSurrogate dataContractSurrogate, bool 
alwaysEmitTypeInformation)
                {
                        if (type == null)
@@ -169,7 +168,6 @@
                        return ReadObject ((XmlReader) reader, 
verifyObjectName);
                }
 
-               [MonoTODO]
                public override object ReadObject (XmlReader reader, bool 
verifyObjectName)
                {
                        if (reader == null)
@@ -177,7 +175,13 @@
                        if (verifyObjectName && !IsStartObject (reader))
                                throw new SerializationException (String.Format 
("Expected element was '{0}', but the actual input element was '{1}' in 
namespace '{2}'", root, reader.LocalName, reader.NamespaceURI));
 
-                       throw new NotImplementedException ();
+                       try {
+                               return new JsonSerializationReader (this, 
reader, type, verifyObjectName).ReadRoot ();
+                       } catch (SerializationException) {
+                               throw;
+                       } catch (Exception ex) {
+                               throw new SerializationException 
("Deserialization has failed", ex);
+                       }
                }
 
                public override void WriteObject (Stream stream, object graph)
@@ -222,7 +226,6 @@
                        WriteObjectContent ((XmlWriter) writer, graph);
                }
 
-               [MonoTODO]
                public override void WriteObjectContent (XmlWriter writer, 
object graph)
                {
                        new JsonSerializationWriter (this, writer, type, 
always_emit_type).WriteObjectContent (graph, true, false);

Added: 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs
===================================================================
--- 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs
      2008-01-24 10:00:01 UTC (rev 93777)
+++ 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs
      2008-01-24 10:14:47 UTC (rev 93778)
@@ -0,0 +1,244 @@
+//
+// JsonSerializationReader.cs
+//
+// Author:
+//     Atsushi Enomoto  <[EMAIL PROTECTED]>
+//
+// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Text;
+using System.Xml;
+
+namespace System.Runtime.Serialization.Json
+{
+       class JsonSerializationReader
+       {
+               DataContractJsonSerializer serializer;
+               XmlReader reader;
+               int serialized_object_count;
+               bool verify_object_name;
+               Dictionary<Type, TypeMap> typemaps = new Dictionary<Type, 
TypeMap> ();
+               Type root_type;
+
+               public JsonSerializationReader (DataContractJsonSerializer 
serializer, XmlReader reader, Type rootType, bool verifyObjectName)
+               {
+                       this.serializer = serializer;
+                       this.reader = reader;
+                       this.root_type = rootType;
+                       this.verify_object_name = verifyObjectName;
+               }
+
+               public XmlReader Reader {
+                       get { return reader; }
+               }
+
+               public object ReadRoot ()
+               {
+                       TypeMap rootMap = GetTypeMap (root_type);
+
+                       object v = ReadObject (root_type);
+                       return v;
+               }
+
+               public object ReadObject (Type type)
+               {
+                       if (serialized_object_count ++ == 
serializer.MaxItemsInObjectGraph)
+                               throw new SerializationException (String.Format 
("The object graph exceeded the maximum object count '{0}' specified in the 
serializer", serializer.MaxItemsInObjectGraph));
+
+                       switch (Type.GetTypeCode (type)) {
+                       case TypeCode.String:
+                               return reader.ReadElementContentAsString ();
+                       case TypeCode.Single:
+                               return reader.ReadElementContentAsFloat ();
+                       case TypeCode.Double:
+                               return reader.ReadElementContentAsDouble ();
+                       case TypeCode.Decimal:
+                               return reader.ReadElementContentAsDecimal ();
+                       case TypeCode.Byte:
+                       case TypeCode.SByte:
+                       case TypeCode.Int16:
+                       case TypeCode.Int32:
+                       case TypeCode.UInt16:
+                       case TypeCode.UInt32:
+                               int i = reader.ReadElementContentAsInt ();
+                               if (type.IsEnum)
+                                       return Enum.ToObject (type, i);
+                               else
+                                       return Convert.ChangeType (i, type);
+                       case TypeCode.Int64:
+                       case TypeCode.UInt64:
+                               long l = reader.ReadElementContentAsLong ();
+                               if (type.IsEnum)
+                                       return Enum.ToObject (type, l);
+                               else
+                                       return Convert.ChangeType (l, type);
+                       case TypeCode.Boolean:
+                               return reader.ReadElementContentAsBoolean ();
+                       default:
+                               if (type == typeof (Guid)) {
+                                       return new Guid 
(reader.ReadElementContentAsString ());
+                               } else if (type == typeof (Uri)) {
+                                       return new Uri 
(reader.ReadElementContentAsString ());
+                               } else if (type == typeof (XmlQualifiedName)) {
+                                       string s = 
reader.ReadElementContentAsString ();
+                                       int idx = s.IndexOf (':');
+                                       return idx < 0 ? new XmlQualifiedName 
(s) : new XmlQualifiedName (s.Substring (0, idx), s.Substring (idx + 1));
+                               } else if (type != typeof (object)) {
+                                       // strongly-typed object
+                                       if (reader.IsEmptyElement) {
+                                               // empty -> null array or object
+                                               reader.Read ();
+                                               return null;
+                                       }
+
+                                       Type ct = GetCollectionType (type);
+                                       if (ct != null) {
+                                               return 
DeserializeGenericCollection (type, ct);
+                                       } else {
+                                               TypeMap map = GetTypeMap (type);
+                                               return map.Deserialize (this);
+                                       }
+                               }
+                               else
+                                       return ReadInstanceDrivenObject ();
+                       }
+               }
+
+               object ReadInstanceDrivenObject ()
+               {
+                       string v = reader.ReadElementContentAsString ();
+                       if (v.Length == 0)
+                               return String.Empty;
+                       if (v [0] == '"') {
+                               if (v [v.Length - 1] != '"')
+                                       throw new SerializationException ("JSON 
string should terminate with '\"'");
+                               return v.Substring (1, v.Length - 2);
+                       }
+                       switch (v) {
+                       case "true":
+                               return true;
+                       case "false":
+                               return false;
+                       case "null":
+                               return null;
+                       }
+                       int i;
+                       if (int.TryParse (v, NumberStyles.None, 
CultureInfo.InvariantCulture, out i))
+                               return i;
+                       long l;
+                       if (long.TryParse (v, NumberStyles.None, 
CultureInfo.InvariantCulture, out l))
+                               return l;
+                       ulong ul;
+                       if (ulong.TryParse (v, NumberStyles.None, 
CultureInfo.InvariantCulture, out ul))
+                               return ul;
+                       double dbl;
+                       if (double.TryParse (v, NumberStyles.None, 
CultureInfo.InvariantCulture, out dbl))
+                               return dbl;
+                       decimal dec;
+                       if (decimal.TryParse (v, NumberStyles.None, 
CultureInfo.InvariantCulture, out dec))
+                               return dec;
+                       throw new SerializationException (String.Format 
("Invalid JSON input: {0}", v));
+               }
+
+               string FormatTypeName (Type type)
+               {
+                       return type.Namespace == null ? type.Name : 
String.Format ("{0}:#{1}", type.Name, type.Namespace);
+               }
+
+               string ToRuntimeTypeName (string s)
+               {
+                       int idx = s.IndexOf (":#", StringComparison.Ordinal);
+                       return idx < 0 ? s : String.Concat (s.Substring (idx + 
2), ".", s.Substring (0, idx));
+               }
+
+               Type GetCollectionType (Type type)
+               {
+                       if (type.IsArray)
+                               return type.GetElementType ();
+                       if (type.IsGenericType) {
+                               // returns T for ICollection<T>
+                               Type gt = type.GetGenericTypeDefinition ();
+                               if (gt == typeof (ICollection<>))
+                                       return type.GetGenericArguments () [0];
+                       }
+                       if (typeof (IList).IsAssignableFrom (type))
+                               // return typeof(object) for mere collection.
+                               return typeof (object);
+                       else
+                               return null;
+               }
+
+               object DeserializeGenericCollection (Type collectionType, Type 
elementType)
+               {
+                       reader.ReadStartElement ();
+                       object ret;
+                       if (typeof (IList).IsAssignableFrom (collectionType)) {
+                               IList c = collectionType.IsArray ?
+                                       new ArrayList () :
+                                       (IList) Activator.CreateInstance 
(collectionType);
+                               for (reader.MoveToContent (); reader.NodeType 
!= XmlNodeType.EndElement; reader.MoveToContent ()) {
+                                       if (!reader.IsStartElement ("item"))
+                                               throw new 
SerializationException (String.Format ("Expected element 'item', but found 
'{0}' in namespace '{1}'", reader.LocalName, reader.NamespaceURI));
+                                       Type et = elementType == typeof 
(object) || elementType.IsAbstract ? null : elementType;
+                                       if (et == null) {
+                                               string typeName = 
reader.GetAttribute ("__type");
+                                               if (typeName != null)
+                                                       et = Type.GetType 
(ToRuntimeTypeName (typeName), false);
+                                       }
+                                       object elem = ReadObject (et ?? typeof 
(object));
+                                       c.Add (elem);
+                               }
+                               ret = collectionType.IsArray ? ((ArrayList) 
c).ToArray (elementType) : c;
+                       } else {
+                               object c = Activator.CreateInstance 
(collectionType);
+                               MethodInfo add = collectionType.GetMethod 
("Add", new Type [] {elementType});
+                               for (reader.MoveToContent (); reader.NodeType 
!= XmlNodeType.EndElement; reader.MoveToContent ()) {
+                                       if (!reader.IsStartElement ("item"))
+                                               throw new 
SerializationException (String.Format ("Expected element 'item', but found 
'{0}' in namespace '{1}'", reader.LocalName, reader.NamespaceURI));
+                                       object elem = ReadObject (elementType);
+                                       add.Invoke (c, new object [] {elem});
+                               }
+                               ret = c;
+                       }
+
+                       reader.ReadEndElement ();
+                       return ret;
+               }
+
+               TypeMap GetTypeMap (Type type)
+               {
+                       TypeMap map;
+                       if (!typemaps.TryGetValue (type, out map)) {
+                               map = TypeMap.CreateTypeMap (type);
+                               typemaps [type] = map;
+                       }
+                       return map;
+               }
+       }
+}


Property changes on: 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/TypeMap.cs
===================================================================
--- 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/TypeMap.cs
      2008-01-24 10:00:01 UTC (rev 93777)
+++ 
trunk/olive/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/TypeMap.cs
      2008-01-24 10:14:47 UTC (rev 93778)
@@ -124,6 +124,34 @@
                                outputter.Writer.WriteEndElement ();
                        }
                }
+
+               public object Deserialize (JsonSerializationReader jsr)
+               {
+                       XmlReader reader = jsr.Reader;
+
+                       object ret = Activator.CreateInstance (type, true);
+                       Dictionary<TypeMapMember,bool> filled = new 
Dictionary<TypeMapMember,bool> ();
+
+                       reader.ReadStartElement ();
+                       for (reader.MoveToContent (); reader.NodeType != 
XmlNodeType.EndElement; reader.MoveToContent ()) {
+                               bool consumed = false;
+                               for (int i = 0; i < members.Length; i++) {
+                                       TypeMapMember mm = members [i];
+                                       if (mm.Name == reader.LocalName && 
reader.NamespaceURI == String.Empty) {
+                                               if (filled.ContainsKey (mm))
+                                                       throw new 
SerializationException (String.Format ("Object content '{0}' for '{1}' already 
appeared in the reader", reader.LocalName, type));
+                                               mm.SetMemberValue (ret, 
jsr.ReadObject (mm.Type));
+                                               filled [mm] = true;
+                                               consumed = true;
+                                               break;
+                                       }
+                               }
+                               if (!consumed)
+                                       reader.Skip ();
+                       }
+                       reader.ReadEndElement ();
+                       return ret;
+               }
        }
 
        abstract class TypeMapMember
@@ -154,7 +182,11 @@
                        get { return dma != null ? dma.Order : -1; }
                }
 
+               public abstract Type Type { get; }
+
                public abstract object GetMemberOf (object owner);
+
+               public abstract void SetMemberValue (object owner, object 
value);
        }
 
        class TypeMapField : TypeMapMember
@@ -167,10 +199,19 @@
                        this.field = fi;
                }
 
+               public override Type Type {
+                       get { return field.FieldType; }
+               }
+
                public override object GetMemberOf (object owner)
                {
                        return field.GetValue (owner);
                }
+
+               public override void SetMemberValue (object owner, object value)
+               {
+                       field.SetValue (owner, value);
+               }
        }
 
        class TypeMapProperty : TypeMapMember
@@ -183,9 +224,18 @@
                        this.property = pi;
                }
 
+               public override Type Type {
+                       get { return property.PropertyType; }
+               }
+
                public override object GetMemberOf (object owner)
                {
                        return property.GetValue (owner, null);
                }
+
+               public override void SetMemberValue (object owner, object value)
+               {
+                       property.SetValue (owner, value, null);
+               }
        }
 }

Modified: 
trunk/olive/class/System.ServiceModel.Web/System.ServiceModel.Web.dll.sources
===================================================================
--- 
trunk/olive/class/System.ServiceModel.Web/System.ServiceModel.Web.dll.sources   
    2008-01-24 10:00:01 UTC (rev 93777)
+++ 
trunk/olive/class/System.ServiceModel.Web/System.ServiceModel.Web.dll.sources   
    2008-01-24 10:14:47 UTC (rev 93778)
@@ -7,6 +7,7 @@
 System.Runtime.Serialization.Json/IXmlJsonWriterInitializer.cs
 System.Runtime.Serialization.Json/JsonReader.cs
 System.Runtime.Serialization.Json/JsonReaderWriterFactory.cs
+System.Runtime.Serialization.Json/JsonSerializationReader.cs
 System.Runtime.Serialization.Json/JsonSerializationWriter.cs
 System.Runtime.Serialization.Json/JsonWriter.cs
 System.Runtime.Serialization.Json/TypeMap.cs

Modified: 
trunk/olive/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/ChangeLog
===================================================================
--- 
trunk/olive/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/ChangeLog
  2008-01-24 10:00:01 UTC (rev 93777)
+++ 
trunk/olive/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/ChangeLog
  2008-01-24 10:14:47 UTC (rev 93778)
@@ -1,3 +1,7 @@
+2008-01-24  Atsushi Enomoto  <[EMAIL PROTECTED]>
+
+       * DataContractJsonSerializerTest.cs : some more deserialization tests.
+
 2008-01-22  Atsushi Enomoto  <[EMAIL PROTECTED]>
 
        * JsonWriterTest.cs : added test for writing __type attribute.

Modified: 
trunk/olive/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs
===================================================================
--- 
trunk/olive/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs
  2008-01-24 10:00:01 UTC (rev 93777)
+++ 
trunk/olive/class/System.ServiceModel.Web/Test/System.Runtime.Serialization.Json/DataContractJsonSerializerTest.cs
  2008-01-24 10:14:47 UTC (rev 93778)
@@ -923,7 +923,76 @@
                }
 
                [Test]
+               public void DeserializeString ()
+               {
+                       Assert.AreEqual ("ABC", Deserialize ("\"ABC\"", typeof 
(string)));
+               }
+
+               [Test]
+               public void DeserializeInt ()
+               {
+                       Assert.AreEqual (5, Deserialize ("5", typeof (int)));
+               }
+
+               [Test]
+               public void DeserializeArray ()
+               {
+                       int [] ret = (int []) Deserialize ("[5,6,7]", typeof 
(int []));
+                       Assert.AreEqual (5, ret [0], "#1");
+                       Assert.AreEqual (6, ret [1], "#2");
+                       Assert.AreEqual (7, ret [2], "#3");
+               }
+
+               [Test]
+               public void DeserializeArrayUntyped ()
+               {
+                       object [] ret = (object []) Deserialize ("[5,6,7]", 
typeof (object []));
+                       Assert.AreEqual (5, ret [0], "#1");
+                       Assert.AreEqual (6, ret [1], "#2");
+                       Assert.AreEqual (7, ret [2], "#3");
+               }
+
+               [Test]
+               public void DeserializeMixedArray ()
+               {
+                       object [] ret = (object []) Deserialize 
("[5,\"6\",false]", typeof (object []));
+                       Assert.AreEqual (5, ret [0], "#1");
+                       Assert.AreEqual ("6", ret [1], "#2");
+                       Assert.AreEqual (false, ret [2], "#3");
+               }
+
+               [Test]
                [ExpectedException (typeof (SerializationException))]
+               public void DeserializeEmptyAsString ()
+               {
+                       // it somehow expects "root" which should have been 
already consumed.
+                       Deserialize ("", typeof (string));
+               }
+
+               [Test]
+               [ExpectedException (typeof (SerializationException))]
+               public void DeserializeEmptyAsInt ()
+               {
+                       // it somehow expects "root" which should have been 
already consumed.
+                       Deserialize ("", typeof (int));
+               }
+
+               [Test]
+               public void DeserializeEmptyObjectAsString ()
+               {
+                       // looks like it is converted to ""
+                       Assert.AreEqual (String.Empty, Deserialize ("{}", 
typeof (string)));
+               }
+
+               [Test]
+               [ExpectedException (typeof (SerializationException))]
+               public void DeserializeEmptyObjectAsInt ()
+               {
+                       Assert.AreEqual (0, Deserialize ("{}", typeof (int)));
+               }
+
+               [Test]
+               [ExpectedException (typeof (SerializationException))]
                public void DeserializeEnumByName ()
                {
                        // enum is parsed into long

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to