Andy
Andy

Reputation: 349

C# Converting mixed JSON into an object

Yo Guys,

I'm currently trying to pass some mixed JSON, and was wondering if it was possible to do anything like the following?

struct example_data 
{
    public Dictionary<string, List<string>> information {get; set;}
}

class TestClass
{
    static void Main(string[] args)
    {
        string test_string = @"{'EventSpecificInformation':
                                   {
                                   'measure':'' 
                                   ,'Long name':'test_name' 
                                   ,'Short name':'test_s_name' 
                                   ,'Description':''
                                   ,'Status':'Real (Imported)'
                                   ,'Viewers':['Everyone']
                                   ,'Modifiers':['Supervisor only']
                                   ,'calculation':''
                                   }
                               }"

        example_data deserialized_entry = JsonConvert.DeserializeObject<example_data>(test_string)
    }
}

As you would expect the above code snippet fails, but I was hoping I could avoid wrapping each JSON entry in a JSON array or having to create a custom JSON reader in C#.

Any advice on the matter would be greatly appreciated.

Upvotes: 2

Views: 286

Answers (4)

Anu Viswan
Anu Viswan

Reputation: 18155

Assuming that you do not want to use a static model,the problem with the code is that it doesn't match signature of your Json. The Json comprises of a Dictionary<string,Dictionary<string,List<string>>. However, there is another concern.

Some of the values in inner Dictionary is not List<string>. Instead, they are strings. For example,

'Short name':'test_s_name' 

For this purpose you need to use a a Custom JsonConverter which if the values is not a array, converts the single string value to list. For example, consider the following Custom JsonConverter.

class SingleOrArrayConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(List<T>));
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Array)
{
return token.ToObject<List<T>>();
}
return new List<T> { token.ToObject<T>() };
}

public override bool CanWrite
{
get { return false; }
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}

Now, you could deserialize your Json as

string test_string = @"{'EventSpecificInformation':
                                   {
                                   'measure':'' 
                                   ,'Long name':'test_name' 
                                   ,'Short name':'test_s_name' 
                                   ,'Description':''
                                   ,'Status':'Real (Imported)'
                                   ,'Viewers':['Everyone']
                                   ,'Modifiers':['Supervisor only']
                                   ,'calculation':''
                                   }
                               }";

var deserialized_entry = JsonConvert.DeserializeObject<Dictionary<string,Dictionary<string, List<string>>>>(test_string,new SingleOrArrayConverter<string>());

Output

enter image description here

Upvotes: 0

Trevor
Trevor

Reputation: 8004

As you would expect the above code snippet fails

string test_string = @"{'EventSpecificInformation':
                               {
                               'measure':'' 
                               ,'Long name':'test_name' 
                               ,'Short name':'test_s_name' 
                               ,'Description':''
                               ,'Status':'Real (Imported)'
                               ,'Viewers':['Everyone']
                               ,'Modifiers':['Supervisor only']
                               ,'calculation':''
                               }
                           }"

In the above you're clearly missing an ending ; at test_string assignment, this wont compile, fix this first (I'm sure it's a type-o). Next, this isn't valid json, you see all the ' in that json, it should be quotes: ". So in short, just replace the bad characters...

 string test_string = @"{'EventSpecificInformation':
                               {
                               'measure':'' 
                               ,'Long name':'test_name' 
                               ,'Short name':'test_s_name' 
                               ,'Description':''
                               ,'Status':'Real (Imported)'
                               ,'Viewers':['Everyone']
                               ,'Modifiers':['Supervisor only']
                               ,'calculation':''
                               }
                           }".Replace("'", "\"");

Note - As far as deserializing your json, create a new question with what you've tried (after fixing this), what isn't working and expected output; you've multiple issues, let's address one at a time.

Upvotes: 2

Krishna Varma
Krishna Varma

Reputation: 4250

You can push the results to Dictionary

string test_string = @"{'EventSpecificInformation':
                        {
                        'measure':'' 
                        ,'Long name':'test_name' 
                        ,'Short name':'test_s_name' 
                        ,'Description':''
                        ,'Status':'Real (Imported)'
                        ,'Viewers':['Everyone']
                        ,'Modifiers':['Supervisor only']
                        ,'calculation':''
                        }
                    }".Replace("'", "\""); 

var results = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, object>>>(test_string);

Upvotes: 0

rbonestell
rbonestell

Reputation: 439

Sounds like what you're looking for is to parse a JSON string into a dynamic object, like so:

dynamic myObject = JsonConvert.DeserializeObject(@"{'EventSpecificInformation':
                               {
                               'measure':'' 
                               ,'Long name':'test_name' 
                               ,'Short name':'test_s_name' 
                               ,'Description':''
                               ,'Status':'Real (Imported)'
                               ,'Viewers':['Everyone']
                               ,'Modifiers':['Supervisor only']
                               ,'calculation':''
                               }
                           }");

string desc = myObject.EventSpecificInformation.Description;
string longName = myObject.EventSpecificInformation["Long name"];

This is likely your best option if you don't have an explicit static model for your JSON input. For properties without a space in their name you can reference them directly using member access syntax, for those with a space you can reference them using indexer access syntax.

Upvotes: 3

Related Questions