2

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.

Andy
  • 339
  • 3
  • 17
  • 8
    What is "mixed" JSON? It's just JSON. –  Feb 14 '20 at 15:21
  • check this out https://stackoverflow.com/a/8972079/7968203, should do what you want if i understand you correctly – Isparia Feb 14 '20 at 15:22
  • or this https://stackoverflow.com/questions/22410511/how-can-i-deserialize-json-containing-delimited-json – nilsK Feb 14 '20 at 15:23
  • 3
    `test_string = test_string.Replace("'", "\"");` Also, you're missing a `;` at the end of `test_string` assignment. You need to replace `'` with `"`, it will then be valid. – Trevor Feb 14 '20 at 15:26
  • By mixed, I mean a mixture of JSON objects and JSON arrays. – Andy Feb 14 '20 at 15:36
  • @Çöđěxěŕ - The semi-colon is a typo, and this string is read fine, even with single quotes. – Andy Feb 14 '20 at 15:37
  • @Andy it's not valid `json`... didn't say it *couldn't be read*. – Trevor Feb 14 '20 at 15:40
  • @Andy We refer to JSON that contains objects and arrays as simply "JSON". –  Feb 14 '20 at 15:53

4 Answers4

3

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.

rbonestell
  • 420
  • 4
  • 13
  • This is what I ended up doing, thanks for your suggestion! Sorry, it took me so long to update. Marking your answer as correct! – Andy Apr 02 '20 at 15:41
2

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.

Trevor
  • 7,777
  • 6
  • 31
  • 50
  • It parses fine. I was hoping I could take my non-array objects, and have C# just make a size one list with the entry. – Andy Feb 14 '20 at 15:39
  • Shouldn't `JsonConvert.DeserializeObject("{'a':'aa','b':'bb'}")` successfully deserialize ? Correct me i am wrong, but Single Quotes should not be a problem – Anu Viswan Feb 14 '20 at 15:48
  • @AnuViswan yes, it will deserialize `'`, the problem is it's not valid `json`, it fails all RFC's... If trying to deserialize into a type, it will fail. – Trevor Feb 14 '20 at 15:56
  • @Andy to make the size one list, you need to use a Custom JsonConverter which does the same. Please check my answer. – Anu Viswan Feb 14 '20 at 16:01
  • @Çöđěxěŕ How about deserializing to `Dictionary>`, with help of a JsonConverter which Converts Single objects to Array ? Could you pls check my answer ? – Anu Viswan Feb 14 '20 at 16:03
0

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);
Krishna Varma
  • 4,238
  • 2
  • 10
  • 25
0

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

Anu Viswan
  • 17,797
  • 2
  • 22
  • 51