CustomConverter不能获取对象的名称

时间:2016-08-15 13:20:59

标签: c# json json.net json-deserialization

我收到这样的json:

{
    "Bryan": {
        "age": 25,
        "city": "Miami"
    },
    "Jeff": {
        "age": 24,
        "city": "Tokyo"
    }
}

我想反序列化以获取list<String>中人员的姓名。 所以我有CustomJsonConverter

public class JsonObjectsToListConverter : JsonConverter
{

    public JsonObjectsToListConverter()
    {

    }

    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(HashSet<String>));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken jtoken = JToken.Load(reader);
        JObject jObjectCast = jtoken.Value<JObject>();

        List<String> listPers = (from prop in jObjectCast.Properties()
                                select prop.Name).ToList();
        return listPers;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

和一个包含List成员的Person类:

public class Persons
    {
        [JsonConverter(typeof(JsonObjectsToListConverter))]
        public List<String> listPers { get; set; }
    }

问题是CustomConverter返回null,除非我将父对象添加到json中,如:

{"listP":
    {
    "Bryan":{
....
人类中的

[JsonProperty("listP")]

我不了解反序列化过程中会发生什么,以及为什么没有PropertyName属性它无法正常工作。

1 个答案:

答案 0 :(得分:1)

下面的描述非常简化,但非常接近实际的反序列化过程。

JsonConvert.DeserializeObject方法提供字符串和目标类型后,它会开始将您指定类型的结构与字符串结构进行比较。它查找提供的类型的公共属性,并在字符串中搜索相同的属性实例。它不知道您在字符串中指定的json数组应该进入名为“listP”的属性,直到您使用json数组的名称在json和类型之间进行链接。

现在,您无需使用JsonProperty属性指定“listP”属性名称。只要json数组与class属性具有相同的名称就足够了:“listPers”

如果您想简化反序列化的过程,但是,如果没有json本身的额外开销和不必要的属性修饰,那么编写类似于下面的代码会更容易:

public class Persons
{
    public List<String> ListPers { get; set; }
}

public class JsonObjectsToPersonsConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Persons));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        Persons value = new Persons();
        JToken jtoken = JToken.Load(reader);
        JObject jObjectCast = jtoken.Value<JObject>();

        List<String> listPers = (from prop in jObjectCast.Properties()
                                 select prop.Name).ToList();
        return new Persons { ListPers = listPers};
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

并反序列化这样的数据:

var persons = JsonConvert.DeserializeObject<Persons>(
    @"{
        'Bryan': {
            'age': 25,
            'city': 'Miami'
        },
        'Jeff': {
            'age': 24,
            'city': 'Tokyo'
        }
    }", 
    new JsonObjectsToPersonsConverter());