简体   繁体   中英

Deserialize List<string> from Json to List<object>

I have the following json string as a sample for my problem:

{
    "Code": "Admin",
    "Groups":
    [
        "Administrator",
        "Superuser",
        "User"
    ]
}

Also I have a class named User with code like this...

[JsonObject(MemberSerialization.OptIn)]
public class User
{
    public User (string code)
    {
        this.Code = code;
    }

    [JsonProperty]
    public string Code { get; set; }

    [JsonProperty("Groups")]
    private List<UserGroup> groups;
    public List<UserGroup> Groups
    {
       if (groups == null)
           groups = new List<UserGroup>();
       return groups;
    }
}

... and a class named UserGroup with - for this example - only this few code lines:

public class UserGroup
{
    public UserGroup (string code)
    {
        this.Code = code;

        // Some code to fill all the other properties, just by knowing the code.
    }

    public string Code { get; set; }

    // More properties
}

Now, what I want is that the above shown JSON string would be deserialized into an instance of an User and all strings in the "Groups" array should be deserialized into a List<UserGroup> with instances from each of those strings. Also - the other way round - should a User be serialized into an JSON string with only the Code property of the contained UserGroups.

I don't deserialize normally but I create an instance of an User and populate it with this code...

Newtonsoft.Json.JsonConvert.PopulateObject(jsonString, myUserInstance);

... but if I run the code with the above shown JSON string all I get is the following exception:

Newtonsoft.Json.JsonSerializationException: 'Error converting value "Administrator" to type 'UserGroup'.

My final requirement is that, I want the UserGroup to be serialized as an array of strings only if I serialize the User . When I serialize a UserGroup standalone as a root object, it should be serialized normally (with all properties). (For comparison, in Json.Net: Serialize/Deserialize property as a value, not as an object the object is serialized as a string in all situations.)

You are going to have to write a converter for the UserGroup

Here is a simple converter based on what was described in the question

public class UserGroupJsonConverter : JsonConverter {

    public override bool CanConvert(Type objectType) {
        return typeof(UserGroup) == objectType;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
        return new UserGroup((string)reader.Value);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
        writer.WriteValue(((UserGroup)value).Code);
    }
}

And then update the User to be aware of the converter by setting the ItemConverterType of the JsonProperty attribute

[JsonObject(MemberSerialization.OptIn)]
public class User {
    public User(string code) {
        this.Code = code;
    }

    [JsonProperty]
    public string Code { get; set; }

    private List<UserGroup> groups;
    [JsonProperty("Groups", ItemConverterType = typeof(UserGroupJsonConverter))]
    public List<UserGroup> Groups {
        get {
            if (groups == null)
                groups = new List<UserGroup>();
            return groups;
        }
    }
}

This would now allow for the JSON in the example

{
    "Code": "Admin",
    "Groups":
    [
        "Administrator",
        "Superuser",
        "User"
    ]
}

to be deserialized as desired

var user = JsonConvert.DeserializeObject<User>(json);

and to be serialized back into the same format.

var json = JsonConvert.SerializeObject(user);

Administrator is a string, UserGroup is an object so this is a type mismatch. The valid JSON for the scenario laid out in your code is:

{
    "Code": "Admin",
    "Groups":
    [
        {
            "Code":"Administrator"
        },
        {
            "Code":"Superuser"
        },
        {
            "Code":"User"
        }
    ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM