locked
IDataContractSurrogate does not work for Primitive data type RRS feed

  • Question

  • I have a type that I want to serialize it to string and vise versa by DataContractJSonSerializer.
    the serialization works correctly but deserialization end up wit error.
    can anybody help me that what is the problem.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.ServiceModel.Activation;
    using System.IO;
    using System.ServiceModel.Web;
    using System.Runtime.Serialization.Json;
    
    namespace ConsoleApplication
    {
    
        public class MyGuid
        {
            public Guid value;
            public override string ToString()
            {
                return this.value.ToString();
            }
    
            public MyGuid()
            {
            }
    
            public MyGuid(Guid value)
            {
                this.value = value;
            }
        }
    
    
        public class MyGuidToStringSurrogate : IDataContractSurrogate
        {
            #region IDataContractSurrogate Members
    
            public object GetCustomDataToExport(Type clrType, Type dataContractType)
            {
                return null;
            }
    
            public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
            {
                return null;
            }
    
            public Type GetDataContractType(Type type)
            {
                if (typeof(MyGuid) == type)
                {
                    return typeof(string);
                }
                return type;
            }
    
            public object GetDeserializedObject(object obj, Type targetType)
            {
                if (obj is string)
                {
                    MyGuid mystr = new MyGuid(new Guid((string)obj));
                    return mystr;
                }
                return obj;
            }
    
            public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes)
            {
            }
    
            public object GetObjectToSerialize(object obj, Type targetType)
            {
                if (obj is MyGuid)
                {
                    return ((MyGuid)obj).ToString();
                }
                return obj;
            }
    
            public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
            {
                return null;
            }
    
            public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
            {
                return typeDeclaration;
            }
    
            #endregion
        }
    
        [DataContract]
        public class Person
        {
            [DataMember]
            public MyGuid ID;
        }
        class Program
        {
            static void Main(string[] args)
            {
    
                Person p = new Person() { ID = new MyGuid() { value = Guid.NewGuid() } };
    
    
                DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person),null, 100, true, new MyGuidToStringSurrogate(), false);
                
                MemoryStream stream=new MemoryStream();
                ser.WriteObject(stream, p);
                String str=Encoding.Default.GetString(stream.ToArray());
                stream.Position = 0;
                object o=ser.ReadObject(stream);
                stream.Close();
            }
        }
    }
    

    Wednesday, June 17, 2009 10:53 AM

All replies

  • Asking repetitive question is a good practice which could let your question not to be answered.

    Thanks
    Marco
    Another Paradigm Shift
    http://shevaspace.blogspot.com
    Friday, June 19, 2009 7:08 AM
  • Asking repetitive question is a good practice which could let your question not to be answered.

    Thanks
    Marco
    Another Paradigm Shift
    http://shevaspace.blogspot.com
    Thanks for your reply.
    But actualy I did not found any solution yet.
    as you can see in sample program the Person object will serialize to somthing like this {"ID":"796D1197-6C1D-4B97-AAB3-7455E2AC78EE"} as I want to be, insted of
    {"ID":{"value":"796D1197-6C1D-4B97-AAB3-7455E2AC78EE"}}
    but in deserialization it will end up with exception "can't cast string to MyGuid"

    any help would be appritiated.
    Friday, June 19, 2009 2:10 PM
  • I'm still waiting .
    Any solution ?
    Sunday, July 26, 2009 11:59 AM
  • You don't need a surrogate for this scenario, you can use a private data member and leave your public property without the [DataMember] attribute, as shown below. This scenario is described in the post at http://blogs.msdn.com/b/carlosfigueira/archive/2011/09/06/wcf-extensibility-serialization-callbacks.aspx.

        public class Post_e22dcf59_62b7_4de5_a664_1443be243377
        {
            public class MyGuid
            {
                public Guid value;
                public override string ToString()
                {
                    return this.value.ToString();
                }
    
                public MyGuid()
                {
                }
    
                public MyGuid(Guid value)
                {
                    this.value = value;
                }
            }
            [DataContract]
            public class Person
            {
                [DataMember(Name = "ID")]
                private string idField;
    
                public MyGuid ID;
    
                public override string ToString()
                {
                    return string.Format("Person[ID={0}]", this.ID);
                }
    
                [OnSerializing]
                void OnSerializing(StreamingContext context)
                {
                    this.idField = this.ID == null ? null : this.ID.ToString();
                }
    
                [OnDeserialized]
                void OnDeserialized(StreamingContext context)
                {
                    Guid guid;
                    if (Guid.TryParse(this.idField, out guid))
                    {
                        this.ID = new MyGuid { value = guid };
                    }
                    else
                    {
                        this.ID = null;
                    }
                }
            }
            public static void Test()
            {
                DataContractJsonSerializer dcjs = new DataContractJsonSerializer(typeof(Person));
                MemoryStream ms = new MemoryStream();
                dcjs.WriteObject(ms, new Person { ID = new MyGuid { value = Guid.NewGuid() } });
                Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
    
                ms.Position = 0;
                Person p = (Person)dcjs.ReadObject(ms);
                Console.WriteLine(p);
            }
        }
    
    


    Carlos Figueira
    Thursday, September 8, 2011 9:25 PM