2015-09-27 30 views
1

使用我有這樣的枚舉:Java的枚舉:實例枚舉「動態」(更像是一個類的構造函數)與傑克遜

public enum Role { 

Manager("manager"), 
Customer("customer"); 

private String role; 

Role(String role){ 
    this.role = role; 
} 
} 

而且我有這個POJO這是我從一個HTTP請求得到(使用Jerey和傑克遜):

public class UserCredentials { 

private String username; 
private String password; 
private Role role; 

public UserCredentials() { 
} 

public String getUsername() { 
    return username; 
} 

public void setUsername(String username) { 
    this.username = username; 
} 

public String getPassword() { 
    return password; 
} 

public void setPassword(String password) { 
    this.password = password; 
} 

public Role getRole() { 
    return role; 
} 

public void setRole(Role role) { 
    this.role = role; 
} 
} 

最後setter創建了一個錯誤傑克遜真的不知道如何轉換

{ 
"username": "shikloshi", 
"password": "password", 
"role": "admin" 
} 

到一個對象(特別是「角色」Enum)。

我試圖改變二傳手到:

public void setRole(String role) { 
this.role = new Role(role); 
} 

不能完成。

有沒有一種方法來調用枚舉構造函數(或任何其他創建方式 - 例如傑克遜)以更加面向對象的方式(另一種方法是在setter中使用switch-case)?

回答

4

這種情況下的常見解決方案是在Role枚舉中添加public static Role fromString(String)方法。它在內部可能使用switchMap<String, Role>緩存。

例如使用簡單switch

public static Role fromString(String string) { 
    switch (string) { 
     case "manager": return Manager; 
     case "customer": return Customer; 
    } 
    throw new IllegalArgumentException("Invalid role: " + string); 
} 

例如使用緩存:

private static Map<String, Role> cache = new HashMap<>(); 
static { 
    for (Role value : values()) { 
     cache.put(value.role, value); 
    } 
} 

public static Role fromString(String string) { 
    Role role = cache.get(string); 
    if (role == null) { 
     throw new IllegalArgumentException("Invalid role: " + string); 
    } 
    return role; 
} 

其實,@realskeptic在評論中指出, 如果您重命名您的enum值全部大寫,MANAGER,CUSTOMER, 按照慣例推薦, 那麼你可以從受益方法,它在後臺使用一個緩存:

public static Role fromString(String string) { 
    return valueOf(string.toUpperCase()); 
} 

在這種情況下,你不必擔心自己構建的緩存。 如果您提供的字符串值無效,則 會像上面的示例一樣產生IllegalArgumentException(文本略有不同)。

+1

正確,但我想補充一點,如果OP根據約定('MANAGER','CUSTOMER')命名常量,那麼可以通過'Role.valueOf(string.toUpperCase())'來輕鬆完成,內部依賴於地圖。 – RealSkeptic

+0

感謝@RealSkeptic,這是一個很好的建議,更新了我的帖子 – janos

+0

很好的答案和實施。謝謝! – Shikloshi