2016-08-15 51 views
0

的名字,我收到一個JSON這樣的:CustomConverter不工作得到對象

{ 
    "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(); 
    } 
} 

,並列出成員的人等級:

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

的問題是,CustomConverter返回NULL,除非我添加父對象轉換爲JSON,如:

{"listP": 
    { 
    "Bryan":{ 
.... 

and [JsonProperty("listP")] in Persons Class。

我不明白在反序列化過程中會發生什麼,以及爲什麼在沒有PropertyName屬性的情況下無法正常工作。

回答

1

下面的描述非常簡單,但非常接近實際的反序列化過程。

一旦你提供了一個字符串和目標類型的JsonConvert.DeserializeObject方法,它開始比較你指定的類型的結構和字符串的結構。它查找提供的類型的公共屬性,並搜索字符串以查找相同的屬性。它不知道在字符串中指定的json數組應該進入名爲「listP」的屬性,直到您使用json數組的名稱在json和類型之間進行鏈接。

現在,您不必指定「listP」屬性名稱與JsonProperty屬性。這足以讓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()); 
+0

但是,如果我用我的轉換器進行反序列化JSON另一個在每個例子「動物」類中的成員列表相同的結構。我能怎麼做 ?最後,要有一個通用的「轉換器」。 – Neyoh

+0

這是一個權衡。您可以編寫一些通用的將類似結構化數據的數組轉換爲名稱列表的方法,也可以爲每個特定的類創建轉換。在第一種情況下,你必須在json中指定數組名稱。在第二部分中,您可以創建一個轉換器的繼承層次結構,將實際的邏輯轉移到一個基類中,這也可能(令人驚訝!)是一個單獨的列表轉換器。但是我沒有看到你什麼時候需要將「Bryans」和「Jeffs」列表轉換爲動物列表...... – galenus