Can Json.Net handle a List<object>?

前端 未结 2 1470
抹茶落季
抹茶落季 2020-12-05 09:53
List list = LoadUsers();

JObject json = new JObject();

json[\"users\"] = new JValue(list);

Doesn\'t seem to be working?

Error

相关标签:
2条回答
  • 2020-12-05 10:29

    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\"}]"
    }
    
    0 讨论(0)
  • 2020-12-05 10:53

    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()) };
    
    0 讨论(0)
提交回复
热议问题