Search code examples
json.netc++-cli

Recursively deserialize using Json.NET so that the JArray becomes a List in C++/CLI


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?


Solution

  • 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);