Bug 2206 - DataContractJsonSerializer does not work
Summary: DataContractJsonSerializer does not work
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: BCL Class Libraries ()
Version: 4.0
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2011-11-28 00:34 UTC by frankhevans
Modified: 2013-10-01 10:48 UTC (History)
7 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description frankhevans 2011-11-28 00:34:32 UTC
When I run the following code in a windows form application, it deserilizes correctly. On mono/android the result is NULL.


string QueryUrl = "http://ajax.googleapis.com/ajax/services/search/local?v=1.0&rsz=3&safe=active&start=1&q=" + queryString;

WebClient webClient = new WebClient();
string QueryResultString = webClient.DownloadString(QueryUrl);

DataContractJsonSerializer json 
          = new DataContractJsonSerializer(typeof(GoogleSearch));
MemoryStream ms 
          = new MemoryStream(Encoding.Unicode.GetBytes(QueryResultString));
GoogleSearch searchResults = json.ReadObject(ms) as GoogleSearch;

=========================
Possibly related to the following thread...

http://mono-for-android.1047100.n5.nabble.com/Json-Deserialization-fails-tt4924572.html#none
Comment 1 frankhevans 2011-11-28 02:06:42 UTC
Would like to do some more testing to make sure the problem is not on my end. Will try to make an update within the next 24 hours.
Comment 2 frankhevans 2011-11-28 02:12:09 UTC
+		err	{System.Runtime.Serialization.SerializationException: Deserialization has failed ---> System.InvalidCastException: Cannot cast from source type to destination type.
  at System.Runtime.Serialization.Json.JsonSerializationReader.DeserializeGenericCollection (System.Type collectionType, System.Type elementType) [0x00277] in /home/jon/Development/xamarin/mono/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs:314 
  at System.Runtime.Serialization.Json.JsonSerializationReader.ReadObject (System.Type type) [0x00375] in /home/jon/Development/xamarin/mono/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs:149 
  at System.Runtime.Serialization.Json.TypeMap.Deserialize (System.Runtime.Serialization.Json.JsonSerializationReader jsr) [0x000ee] in /home/jon/Development/xamarin/mono/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/TypeMap.cs:230 
  at System.Runtime.Serialization.Json.JsonSerializationReader.ReadObject (System.Type type) [0x00388] in /home/jon/Development/xamarin/mono/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs:152 
  at System.Runtime.Serialization.Json.TypeMap.Deserialize (System.Runtime.Serialization.Json.JsonSerializationReader jsr) [0x000ee] in /home/jon/Development/xamarin/mono/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/TypeMap.cs:230 
  at System.Runtime.Serialization.Json.JsonSerializationReader.ReadObject (System.Type type) [0x00388] in /home/jon/Development/xamarin/mono/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs:152 
  at System.Runtime.Serialization.Json.JsonSerializationReader.ReadRoot () [0x0000d] in /home/jon/Development/xamarin/mono/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/JsonSerializationReader.cs:66 
  at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject (System.Xml.XmlReader reader, Boolean verifyObjectName) [0x00045] in /home/jon/Development/xamarin/mono/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs:190 
  --- End of inner exception stack trace ---
  at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject (System.Xml.XmlReader reader, Boolean verifyObjectName) [0x00062] in /home/jon/Development/xamarin/mono/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs:194 
  at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject (System.Xml.XmlDictionaryReader reader, Boolean verifyObjectName) [0x00000] in /home/jon/Development/xamarin/mono/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs:179 
  at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject (System.Xml.XmlDictionaryReader reader) [0x00000] in /home/jon/Development/xamarin/mono/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs:169 
  at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject (System.IO.Stream stream) [0x00018] in /home/jon/Development/xamarin/mono/mcs/class/System.ServiceModel.Web/System.Runtime.Serialization.Json/DataContractJsonSerializer.cs:161 
  at MonoDroid.Samples.MapsDemo.TaskListActivity.GoogleSearch (System.String queryString) [0x00043] in C:\DEV\mondroid\MapsDemo\MapsDemo\TaskListActivity.cs:94 }	System.Runtime.Serialization.SerializationException
Comment 3 Jonathan Pobst 2011-11-28 18:15:15 UTC
Can you test this on Mono on the desktop so we know if it's a Mono bug or a Mono for Android bug?
Comment 4 Jonathan Pryor 2011-12-06 11:21:34 UTC
It's a Mono for Android bug.

The problem is that System.Runtime.Serialization doesn't invoke the Java.Lang.Object default constructor, and thus the corresponding Java-side object is never created. Result: the Handle property is always IntPtr.Zero, which is a total fail if (when) you try to pass that instance to Java code (as Java will just receive a null reference).
Comment 5 Jonathan Pryor 2011-12-06 11:22:26 UTC
The fix is to find whatever Serialization mechanism is supposed to be used as a pre- or post-instantiation "callback" so that we can create the appropriate Java side object. Unfortunately, I forget what this mechanism is...
Comment 6 Atsushi Eno 2011-12-06 12:35:25 UTC
I don't think the callback thing is about DataContract serialization (maybe runtime formatter binary serialization http://msdn.microsoft.com/en-us/library/system.runtime.serialization.ideserializationcallback.aspx ). WCF serialization has no such customization hook.
Comment 7 Jonathan Pryor 2011-12-06 22:19:55 UTC
@eno: I believe the OnDeserializingAttribute can be used for DataContract serialization:

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.ondeserializingattribute.aspx

Binary serialization isn't going to work as Java.Lang.Object isn't [Serializable], so it can't be serialized anyway.
Comment 8 frankhevans 2011-12-06 22:50:58 UTC
I just found that I could make deserialization by replacing all array[] with List<>

For example...
change:  PhoneNumber[]  numbers
To:      List<PhoneNumber> numbers
Comment 9 frankhevans 2011-12-07 00:27:45 UTC
change: 
        [DataMember(Order = 11)]
        public PhoneNumber[]  phoneNumbers;
To:          
        [DataMember(Order = 11)]
        public List<PhoneNumber> phoneNumbers;
Comment 10 Jonathan Pryor 2011-12-08 15:46:02 UTC
Java.Lang.Object has [OnDeserialized] support in commit 14d9a9cc, so that Java.Lang.Object subclasses can be serialized to JSON and properly deserialized from JSON (comment 4 and comment 5).

However, now that I re-read the original report about the InvalidCastException, I think I was mistaken about the cause of the bug. I'm not sure why there was an InvalidCastException. :-(
Comment 11 PJ 2013-05-21 11:29:37 UTC
Marking fixed as per comment 10. If you are still experiencing the issue, please re-open.
Comment 12 JohanO 2013-10-01 03:00:22 UTC
Hi Guys, I am experiencing the exact issue with Mono for Android - the same code works fine for Win8 RT.

public T ToObject<T>()
        {
            if (DataStream == null)
                return default(T);

            
            DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(T));
            object instance = json.ReadObject(DataStream);
            return (T)instance;
        }

Here's the type being passed. It's a service reference generated member:

 public partial class BranchInfoResult : object, System.ComponentModel.INotifyPropertyChanged {
        
        private System.Nullable<float> SalesCompDollarsField;
        
        private System.Nullable<float> SalesDollarsField;
        
        private System.Nullable<float> SalesVarField;
        
        [System.Runtime.Serialization.DataMemberAttribute()]
        public System.Nullable<float> SalesCompDollars {
            get {
                return this.SalesCompDollarsField;
            }
            set {
                if ((this.SalesCompDollarsField.Equals(value) != true)) {
                    this.SalesCompDollarsField = value;
                    this.RaisePropertyChanged("SalesCompDollars");
                }
            }
        }
        
        [System.Runtime.Serialization.DataMemberAttribute()]
        public System.Nullable<float> SalesDollars {
            get {
                return this.SalesDollarsField;
            }
            set {
                if ((this.SalesDollarsField.Equals(value) != true)) {
                    this.SalesDollarsField = value;
                    this.RaisePropertyChanged("SalesDollars");
                }
            }
        }
        
        [System.Runtime.Serialization.DataMemberAttribute()]
        public System.Nullable<float> SalesVar {
            get {
                return this.SalesVarField;
            }
            set {
                if ((this.SalesVarField.Equals(value) != true)) {
                    this.SalesVarField = value;
                    this.RaisePropertyChanged("SalesVar");
                }
            }
        }
        
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
        
        protected void RaisePropertyChanged(string propertyName) {
            System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
            if ((propertyChanged != null)) {
                propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }
    }
Comment 13 Jonathan Pryor 2013-10-01 10:48:44 UTC
@JohanO: That looks to be a WCF-related bug. Please re-file in the Product=Class Libraries Component=WCF page.