1

I'm trying to retrieve all data from a JSON file to my C# application. But now the problem is that the field "info" in my json file is sometimes from the type string but it can also be the type object.

{
    [
        {
            "id":"147786",
            "canUpdate":true,
            "canDelete":true,
            "canArchive":true,
            "hasChildren":false,
            "info": "Test"
        },
        {
            "id":"147786",
            "canUpdate":true,
            "canDelete":true,
            "canArchive":true,
            "hasChildren":false,
            "info": [{"id"="1","messages":"true"}]
        }
    ]
}

well my model you can see here below, when there are only strings in my json file i can retrieve the data without any exception but when there are also objects in the info field then i get the error can't convert the value.

Is there a way to fix this on an easy way?

   public string id { get; set; }

    public string canUpdate { get; set; }


    public string info { get; set; }
Feren
  • 61
  • 2
  • 7
  • 1
    Maybe `public dynamic info { get; set; }` – Reza Aghaei Jan 26 '20 at 16:53
  • Or [How to handle both a single item and an array for the same property using JSON.net](https://stackoverflow.com/a/18997172/7444103) (*managed*). – Jimi Jan 26 '20 at 17:08
  • Duplicate of the previous: [How to handle json that returns both a string and a string array?](https://stackoverflow.com/a/22053420/7444103), just simpler. – Jimi Jan 26 '20 at 17:11
  • 1
    If the types are compatible, then the linked posts will do the trick, but a string and an array of objects are not compatible. – Reza Aghaei Jan 26 '20 at 17:15
  • You may also want to take a look at [TypeNameHandling setting](https://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling.htm), however you don't have any `$type` in your objects. – Reza Aghaei Jan 26 '20 at 17:57
  • @Reza Aghaei It would work. The OP, of course, would need to change the return type after `if (token.Type == JTokenType.Array)`. The linked answer converts it to a `List` (strings, there). Here, you can return another object type, depending on the desired result. That answer, as it is, should work anyway, but it would probably return a `List`. You could also parse it later. Or not parse it all, or convert it. Btw, this: `"info": [{"id"="1","messages":"true"}]` appears to be wrong. – Jimi Jan 26 '20 at 18:12
  • @Jimi Yes if you use `List` (or probably a `List`) then the types are compatible and the linked solution will work. But I think a `List` will not be better than a dynamic object. – Reza Aghaei Jan 26 '20 at 18:18
  • @Reza Aghaei Yes, well, I mean it would work directly (with no other edits, I think) if you just change the type of `Info` to `object` or `List` -- I didn't mean to say that an object type is better then using dynamic (btw, I didn't even notice before that you posted an answer). I mean that implementing a custom converter to return a concrete type (making the necessary modifications to the code shown in those answers) would be a good choice, IMO. It depends on what the OP is going to use this output for. – Jimi Jan 26 '20 at 18:22
  • @Jimi I also prefer having specific types and I agree, a custom `Converter` can handle the case. – Reza Aghaei Jan 26 '20 at 18:54

1 Answers1

2

As an option you can define the info as dynamic:

public dynamic info { get; set; }

Example

Consider the following json string:

string json = @"
[
    { 'P1': 'X', 'P2': 'Y' },
    { 'P1': 'X', 'P2': [ 
        {'P11':'XX', 'P22':'YY'}, 
        {'P11':'XX', 'P22':'YY'}] 
    }
]";

You can define such model to deserialize it:

public class C
{
    public string P1 { get; set; }
    public dynamic P2 { get; set; }
}

And deserialize it like this:

var obj = JsonConvert.DeserializeObject<C[]>(json);

Note

If the number of dynamic properties is too much then usually there is no point in creating the class and the following code will be enough:

var obj = (dynamic)JsonConvert.DeserializeObject(json);
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398