Can Json.Net handle a List<object>?

36,309

Solution 1

A JValue can only contain simple values like strings, ints, booleans, dates and the like. It cannot contain a complex object. I suspect what you really want is this:

List<User> list = LoadUsers();

JObject json = new JObject();

json["users"] = JToken.FromObject(list);

The above will convert the list of User objects into a JArray of JObjects representing the users, then assign that to the users property on the new JObject. You can confirm this by examining the Type property of json["users"] and see that it is Array.

In contrast, if you do json["users"] = new JValue(JsonConvert.SerializeObject(list)) as was suggested in another answer to this question (now deleted), you will probably not get the result you are looking for. That approach will serialize the list of users to a string, create a simple JValue from that, and then assign the JValue to the users property on the JObject. If you examine the Type property of json["users"], you will see that it is String. What this means is, if you later try to convert the JObject to JSON by using json.ToString(), you will get double-serialized output instead of the JSON you probably expect.

Here is a short demo to illustrate the difference:

class Program
{
    static void Main(string[] args)
    {
        List<User> list = new List<User>
        {
            new User { Id = 1, Username = "john.smith" },
            new User { Id = 5, Username = "steve.martin" }
        };

        JObject json = new JObject();

        json["users"] = JToken.FromObject(list);
        Console.WriteLine("First approach (" + json["users"].Type + "):");
        Console.WriteLine();
        Console.WriteLine(json.ToString(Formatting.Indented));

        Console.WriteLine();
        Console.WriteLine(new string('-', 30));
        Console.WriteLine();

        json["users"] = new JValue(JsonConvert.SerializeObject(list));
        Console.WriteLine("Second approach (" + json["users"].Type + "):");
        Console.WriteLine();
        Console.WriteLine(json.ToString(Formatting.Indented));
    }

    class User
    {
        public int Id { get; set; }
        public string Username { get; set; }
    }
}

Output:

First approach (Array):

{
  "users": [
    {
      "Id": 1,
      "Username": "john.smith"
    },
    {
      "Id": 5,
      "Username": "steve.martin"
    }
  ]
}

------------------------------

Second approach (String):

{
  "users": "[{\"Id\":1,\"Username\":\"john.smith\"},{\"Id\":5,\"Username\":\"steve.martin\"}]"
}

Solution 2

I had this issue, you can now use JArray to get this done, if you just want the array items with no root name.

var json = JArray.FromObject(LoadUsers());

If you want the root name of the json array to be "users", you can use

var json = new JObject { ["users"] = JToken.FromObject(LoadUsers()) };
Share:
36,309
mrblah
Author by

mrblah

test testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest testtest test asdf asdf

Updated on January 05, 2020

Comments

  • mrblah
    mrblah over 4 years
    List<User> list = LoadUsers();
    
    JObject json = new JObject();
    
    json["users"] = new JValue(list);
    

    Doesn't seem to be working?

    Error:

    Could not determine JSON object type for type System.Collections.Generic.List`1