3

I have a JSON like this one:

{
    "name" : "MyCustomName",
    "my_node" : {
        "name" : "my_node_name"
    },
    "dict1":"value1",
    "dict2":"value2",
    "dict3":"value3",
    ...
}

and an object:

class Node{
    string value;
}

class Sample:IDictionary<string, string>{ 
    Node node;
    string name; 
} 

Node and Name in Sample class are always present. The thing is I don't know how many "dictN" fields will be... and that's the point.

And the question is: How to Deserialize that JSON to this Object?

7
  • 2
    It's good you have a point... and the question would be? =) Commented Nov 29, 2012 at 15:52
  • 1
    do you have control of how the json is created. Can you use an array were "dict": ["val1", "val2", "val3..."]? Commented Nov 29, 2012 at 15:53
  • Unfortunately no. It came from an API. Commented Nov 29, 2012 at 15:54
  • Do you have control over the object classes that you're deserializing to? As long as they provide the same API, can you change how they are implemented? Commented Nov 29, 2012 at 15:56
  • Is there a reason you can't use any of the existing libraries? Commented Nov 29, 2012 at 15:58

3 Answers 3

2

Edit: apparently even with field names harmonized, your deserializer just can't cope with specific fields combined with general dictionary fields.

In which case, I'd just advise deserializing as a Dictionary<string, object> and building with the result:

var d = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
Sample s = new Sample();
s.name = (string)d["name"];
Node n = new Node();
n.value = (string)((Dictionary<string, object>)d["my_node"])["name"];
foreach (var key in d.Keys.Except(new string[] { "name", "my_node" }))
{
    s.Add(key, (string)d[key]);
}
Sign up to request clarification or add additional context in comments.

4 Comments

About changes in a class there is no problem to this. I can change Sample.node to a Sample.my_node, that same for a value
Try that and see if it works, then... TBH I'd be surprised if it was able to successfully decide "this value goes in a field, this value goes in the inherited dictionary" though.
Its still not working, and yeah question about passing values in right(Collection) and sometime in left(Fields) can be confuseing:/
In that case, and if no-one else comes up with a better idea, I'd fall back on "Deserialize as a Dictionary<string, object>, play with it in the debugger and see how to manually convert it to your class".
1

INITIAL IDEA

The following is a dictionary serializer. It has one special case of not accepting empty string.

private void SerializePerinatalModel<T>(IDictionary<string, object> dataModel, T perinatalModel)
    {
        Type sourceType = typeof(T);
        foreach (PropertyInfo propInfo in (sourceType.GetProperties()))
        {
            if (dataModel.ContainsKey(propInfo.Name))
            {
                //  if an empty string has been returned don't change the value
                if (dataModel[propInfo.Name].ToNullSafeString() != String.Empty)
                {
                    try
                    {
                        Type localType = propInfo.PropertyType;
                        localType = Nullable.GetUnderlyingType(localType) ?? localType;
                        propInfo.SetValue(perinatalModel, Convert.ChangeType(dataModel[propInfo.Name], localType), null); 
                    }
                    catch (Exception e)
                    {
                        //  ToDo: log update value errors
                    }

                }
            }

        }
    }

but could be made null safe. It does deal with nullable types.

As JSON is essentially a dictionary type then iterating through the top level types should get you there.

This is written in haste so is only a sketch of an idea.

BETTER IDEA Also try using

foreach (var item in JsonData.Where(m => m.Key.Substring(0,4) == "dict"))
{
   // add item to collection
}

might also do the biz.

Comments

1

You can simply have the output in the form of Dictionary<string, object>, try this piece of code instead.

System.Web.Script.Serialization.JavaScriptSerializer s = 
    new System.Web.Script.Serialization.JavaScriptSerializer();

var nodes = s.Deserialize<Dictionary<string, object>>(jsonString);
var dictNodes = nodes.Where(w => w.Key.StartsWith("dict"));

2 Comments

ok.... maybe my example is not good enaugh... But what if there will be fields like "mydict1". I just focused on that there are only two fields which I'm sure that always will be rest of them should goes into container.
So you can achieve it with my code. The essence lies within this line of code nodes.Where(w => w.Key.StartsWith("dict")); which will give you all the nodes having dictN elements after filtration.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.