2013-07-12 163 views
3

我使用JSON從傑克遜序列化問題,如何從Collections.unmodifiableMap?傑克遜序列化Collections.unmodifiable *

我得到的錯誤序列是:

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.util.Collections$UnmodifiableMap, problem: No default constructor found 

我想用SimpleAbstractTypeResolver從然而http://wiki.fasterxml.com/SimpleAbstractTypeResolver我不能得到內部類類型Collections$UnmodifiableMap

Map<Integer, String> emailMap = newHashMap(); 
Account testAccount = new Account(); 
ObjectMapper mapper = new ObjectMapper(); 
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, As.PROPERTY); 
String marshalled ; 
emailMap.put(Integer.valueOf(10), "[email protected]"); 
testAccount.setMemberEmails(emailMap); 

marshalled = mapper.writeValueAsString(testAccount); 
System.out.println(marshalled); 
Account returnedAccount = mapper.readValue(marshalled, Account.class); 
System.out.println(returnedAccount.containsValue("[email protected]")); 


public class Account { 
    private Map<Integer, String> memberEmails = Maps.newHashMap(); 

    public void setMemberEmails(Map<Integer, String> memberEmails) { 
    this.memberEmails = memberEmails; 
    } 

    public Map<Integer, String> getMemberEmails() { 
    return Collections.unmodifiableMap(memberEmails); 
    } 

任何想法?提前致謝。

回答

1

好吧,你碰到的邊緣上下的類型情況與傑克遜。問題的實質是,圖書館會樂於使用你的getter方法來檢索集合和地圖屬性,並且如果這些getter方法返回null,則只能退回到實例化這些集合/地圖。

這可以通過@JsonProperty/@JsonIgnore註釋的組合來解決,但要注意您的JSON輸出中的@class屬性會發生變化。

代碼示例:

public class Account { 
    @JsonProperty("memberEmails") 
    private Map<Integer, String> memberEmails = Maps.newHashMap(); 

    public Account() { 
     super(); 
    } 

    public void setMemberEmails(Map<Integer, String> memberEmails) { 
     this.memberEmails = memberEmails; 
    } 

    @JsonIgnore 
    public Map<Integer, String> getMemberEmails() { 
     return Collections.unmodifiableMap(memberEmails); 
    } 
} 

如果序列化此類測試代碼,你會得到以下JSON:

{ 
    "@class": "misc.stack.pojo.Account", 
    "memberEmails": { 
     "10": "[email protected]", 
     "@class": "java.util.HashMap" 
    } 
} 

這將正確地反序列化。

+0

感謝感知。這完全符合我的目的。是否有一種方法可以在模型類本身沒有回退註釋的情況下具有相同的行爲? – hartraft

+0

@hartraft您可能想要使用的是Jackson Mix In的http://wiki.fasterxml.com/JacksonMixInAnnotations – leo

0

Jackson默認查找默認構造函數。您需要指定@JsonCreator,@JsonProperty註釋以使非空構造函數可以工作。

由於您無法將這些註釋添加到Collections.UnmodifiableCollection中,因此您無法反序列化它。

  1. 你可能並不需要使用修改的Collection被序列化。有什麼意義?反序列化對象時可以這樣做。另外,反序列化的對象將與一個序列化的(複製)不同

  2. 如果您真的需要這樣做,您可以簡單編寫自己的UnmodifiableCollection類。這是非常簡單的,因爲它只是一個底層集合

    public boolean isEmpty() { return c.isEmpty(); } // c is underlying collection 
    

    收集和委託方法調用的包裝,除了修改方法:

    public boolean add(E e) { 
        throw new UnsupportedOperationException(); 
    } 
    ..... 
    
  3. 你也可以調用的方法之一之前序列化來序列化數組。當反序列化建立你的模型對象與創建從陣列收集和吸氣劑返回不可修改的集合來訪問這個集合:

    public Object[] toArray(); 
    public <T> T[] toArray(T[] a); 
    
  4. 您可以在模型中添加@JsonIgnore到您的getter方法,並添加@JsonValue您memberEmails領域。

  5. 您可以創建另一次吸氣(私人和不同的名稱),其標註爲JsonValue爲您現場

+0

adited回答您的更新情況 – Tala

+0

塔拉謝謝!我看着我投入了原來的問題的例子,這確實是不必須序列化unmodifiableMap 的ObjectMapper我有使用DefaultTyping這是造成我的問題一個問題。我已經更新了問題,我可以進一步縮小我的搜索標準,現在有點 – hartraft

+0

我添加選項4和5。我會親自去與4 – Tala