【问题标题】:CustomConverter doesn't works to get names of objectsCustomConverter 无法获取对象的名称
【发布时间】:2016-08-15 13:20:58
【问题描述】:

我收到这样的 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")] 在 Persons 类中。

我不明白反序列化过程中会发生什么,以及为什么没有PropertyName 属性就不能正常工作。

【问题讨论】:

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


    【解决方案1】:

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

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

    现在,您不必使用 JsonProperty 属性指定 "listP" 属性名称。只需将 json 数组与类属性具有相同的名称就足够了:"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());
    

    【讨论】:

    • 但是,如果我使用我的转换器反序列化另一个 JSON,在每个示例的“动物”类的成员列表中具有相同的结构。我能怎么做 ?最后,要有一个通用的“转换器”。
    • 这是一个权衡。您可以编写一些通用的东西来将类似结构的数据数组转换为名称列表,或者为每个特定类创建一个转换。在第一种情况下,您必须在 json.xml 中指定数组名称。在第二个中,您可以创建转换器的继承层次结构,将实际逻辑移动到一个基类中,它也可以(令人惊讶!)本身就是一个列表转换器。但我看不出何时需要将“Bryans”和“Jeffs”列表转换为动物列表...
    猜你喜欢
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-29
    相关资源
    最近更新 更多