0

I have the following json (provided by an API):

[
    {
        "type": "text",
        "values": [
            {
                "value": "Text that is in textfield"
            }
        ]
    },
    {
        "type": "category",
        "values": [
            {
                "value": {
                    "text": "Category title",
                    "color": "#000000"
                }
            }
        ]
    }
]

How do you present such an object as strong type (which C# requires of you) when values.value is of dynamic?

Here is more information on my issue: Trying to map two different types to one value

but I wanted to keep this new question lean.


Sorry to bump, but I still can't get this to work! Any examples of how to serialize this?

I currently have this code to serialize:

[DataContract]
public class MyField
{
    [DataMember]
    public List<MyValue> values { get; set; }
}

[DataContract]
public class MyValue
{
    [DataMember]
    public object value { get; set; } // This will crash because it needs to be both a string and an object with text,color properties??
}

using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(response)))
{
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<MyField>));
    return (List<MyField>)serializer.ReadObject(stream);
}

but it crashes on the values.value bit because it cannot cast to strongly typed... as it is varying.

////edit////

Sureeeely someone has done this before!!!

Community
  • 1
  • 1
Jimmyt1988
  • 20,466
  • 41
  • 133
  • 233

2 Answers2

1

Basically you are going to want to define Value as a Dictionary, since it is dynamic.

As for how you serialize this, it depends on which serializer you are using. Personally I prefer JSON.NET from Newtonsoft. You can find plenty of examples of how to serialize dictionaries into JSON here on SO.

Here is one for using datacontractjsonserializer: Deserialize JSON to Dictionary with DataContractJsonSerializer

Here is an example using json.net: How can I deserialize JSON to a simple Dictionary<string,string> in ASP.NET?

UPDATE

Here is how you can deserialize mixed types in an array with JSON.NET and still keep strong typing. The key is the JSONConverter implementation, which basically instructs the serializer to deserialize as a string or a type (Attribute).

public static void Main()
{
    using (FileStream stream = File.OpenRead("TextFile1.txt"))
    using (StreamReader reader = new StreamReader(stream))
    {
        JsonSerializer ser = new JsonSerializer();
        List<MyField> result = ser.Deserialize<List<MyField>>(new JsonTextReader(reader));
    }       
}





public class MyField
{
    public string type { get; set; }        
    public List<MyValue> values { get; set; }
}


public class MyValue
{
    [JsonConverter(typeof(MyConverter))]
    public object value { get; set; }
}

public class MyAttributes
{
    public string text { get; set; }
    public string color { get; set; }
}


public class MyConverter : JsonConverter
{

    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.String)
        {
            return serializer.Deserialize<string>(reader);
        }
        else
        {
            return serializer.Deserialize<MyAttributes>(reader);
        }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
Community
  • 1
  • 1
Mike Hixson
  • 5,071
  • 1
  • 19
  • 24
  • I couldn't get this to work but I did find this: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable.aspx ISerializable type, I am assuming I can re-run a de-serialization on this type (at work atm but will try when I get home) – Jimmyt1988 Jun 12 '14 at 10:01
  • When I did the Dictionary, it still says System.InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Collections.ICollection' I obviously set the settings as mentioned in the post. – Jimmyt1988 Jun 17 '14 at 21:08
  • YOURS IS PERFECt. MUCH BETTER and I can re-use what I have already done... MANN YOU DESERVE a 6 PACK! NICE WORK DUDEEEe – Jimmyt1988 Jun 17 '14 at 22:29
-1

The DataContractJsonSerializer is useless here...

I finally used Json.Net...

Then just pass your string into the parse (Make sure that it's not an array but an object containing your array)... you can see how I suffixed and prefixed my response with pubes:

JObject jObject = JObject.Parse("{\"data\": " + response + "}");
JToken jData = jObject["data"];

Then you can do whatever you want:

string type = (string)jData["type"];

and ofcourse this means I can now do a switch on the type and then create an object of whatever required type.

Jimmyt1988
  • 20,466
  • 41
  • 133
  • 233