0

I'm deserialisizing JSON using Json.NET in C++/CLI.

Let's say I have the following string:

{
  "StrProp": ["str1", "str2"],
  "Flt": 42.2
}

I would like to get a Dictionary<String^, Object^>^ out of this.

First thing to try then is DeserializeObject:

Dictionary<String^, Object^>^ dict = Json::JsonConvert::DeserializeObject<Dictionary<String^, Object^>^>(json);

However, I find that dict["StrProp"] is a JArray, when I would like it to be Collection type (like array<String^>^).

I realise I can create a JsonConverter of some sort but I'm struggling a bit on how to ensure that instead of parsing a string and returning a JArray, it needs to return a Collection type (like array<>) rather than a specific Json.NET type.

Anyone?

John Go-Soco
  • 886
  • 1
  • 9
  • 20
  • Arrays are so 1970s, favor its `Values()` method to get a very cheap enumerable. If it must be an array then use `Enumerable::ToArray()` to create it from Values. – Hans Passant Nov 13 '19 at 13:30
  • Any Collection type would do. More to the point is how to achieve it. – John Go-Soco Nov 13 '19 at 13:37
  • 1
    Your question sounds very similar to [How do I use JSON.NET to deserialize into nested/recursive Dictionary and List?](https://stackoverflow.com/q/5546142/10263). The answers there might help you, but you will need to translate to C++. – Brian Rogers Nov 13 '19 at 17:38
  • 1
    @BrianRogers That's it! I've modified it for C++/CLI and posted the answer below for posterity. – John Go-Soco Nov 14 '19 at 13:56

1 Answers1

1

A non-LINQ-Select solution for C++/CLI based on @BrianRogers answer found in https://stackoverflow.com/a/19140420/3274353.

Object^ ToObject(JToken^ token)
{
    switch (token->Type)
    {
        case JTokenType::Object:
        {
            Dictionary<String^, Object^>^ result = gcnew Dictionary<String^, Object^>();
            for each (JProperty^ prop in token->Children<JProperty^>())
            {
                result[prop->Name] = ToObject(prop->Value);
            }
            return result;
        }
        case JTokenType::Array:
        {
            List<Object^>^ result = gcnew List<Object^>();
            for each (JValue^ prop in token)
            {
                result->Add(prop->Value);
            }
            return result;
        }
        default:
        {
            return ((JValue^)token)->Value;
        }
    }
}

Object^ Deserialize(String^ json)
{
  return ToObject(JToken::Parse(json));
}

And using it:

Object^ obj = Deserialize(jsonString);
John Go-Soco
  • 886
  • 1
  • 9
  • 20