none
deserializing a JSON object containing array of arrays RRS feed

  • Question

  • I am impelementing a client application programmed against a RESTful service which I do not control.

    One of the methods of the service returns a JSON object containing an array named "values". Its contents are an array of objects containing a long and a double. The inner array is unnamed, the JSON object looks like this...
     
    { "values" : [ [ 100, 200.5 ], [ 110, 210.5 ] ] }
     
    I am trying to declare a class that can consume the inner array but I can't seem to figure out how to use DataContract/DataMember attributes to define such a class.


    [DataContract]
    public class Data
    {
      [DataMember(Name="values")]
      public Inner[] Values { get; set; }
    }

    [DataContract]
    public class Inner
    {
        public long Index { get; set; }
        public double Height { get; set; }
    }
     
    Every thing I try results in the inner Values array being set to null. The deserializer is trying to match field names with the incoming JSON object but there are no field names.

    Any help would be most appreciated!

    John
    Monday, January 19, 2009 9:27 PM

Answers

  • You should receive the values to an array of arrays, then convert them into your data type using the OnDeserialized callback for the serializer:

        public class Post7e066cd7_f139_4c5e_abcb_4e55fac91682  
        {  
            [DataContract]  
            public class Data  
            {  
                public Inner[] Values { getset; }  
     
                [DataMember(Name = "values")]  
                object[][] data;  
     
                [OnDeserialized]  
                public void OnDeserialized(StreamingContext context)  
                {  
                    if (this.data != null)  
                    {  
                        this.Values = new Inner[data.Length];  
                        for (int i = 0; i < this.data.Length; i++)  
                        {  
                            System.Diagnostics.Debug.Assert(this.data[i].Length == 2);  
                            this.Values[i] = new Inner();  
                            this.Values[i].Index = ((IConvertible)this.data[i][0]).ToInt64(null);  
                            this.Values[i].Height = ((IConvertible)this.data[i][1]).ToDouble(null);  
                        }  
                    }  
                }  
     
                public override string ToString()  
                {  
                    StringBuilder sb = new StringBuilder();  
                    sb.Append("Data{Values=");  
                    if (this.Values == null)  
                    {  
                        sb.Append("<<null>>");  
                    }  
                    else 
                    {  
                        sb.Append("[");  
                        for (int i = 0; i < this.Values.Length; i++)  
                        {  
                            if (i > 0) sb.Append(", ");  
                            sb.Append(this.Values[i]);  
                        }  
                        sb.Append("]");  
                    }  
                    sb.Append("}");  
                    return sb.ToString();  
                }  
            }  
     
            [DataContract]  
            public class Inner  
            {  
                [DataMember]  
                public long Index { getset; }  
                [DataMember]  
                public double Height { getset; }  
     
                public override string ToString()  
                {  
                    return String.Format("Inner{{Index={0},Height={1}}}", Index, Height);  
                }  
            }  
     
            const string jsonStr = "{ \"values\" : [ [ 100, 200.5 ], [ 110, 210.5 ] ] }";  
            public static void Test()  
            {  
                MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonStr));  
                DataContractJsonSerializer dcjs = new DataContractJsonSerializer(typeof(Data));  
                Data data = (Data)dcjs.ReadObject(ms);  
                Console.WriteLine(data);  
            }  
        }  
     
    Monday, January 19, 2009 10:10 PM