2013-03-11 52 views
0

我們正在嘗試編寫一個API來創建不同類型的元素。元素具有JPA實體表示。下面的代碼顯示了我們的基本要素結構的樣子(簡化):Spring-MVC,InheritanceType.JOINED,以及JSON對象自動映射到Jackson的實體

import javax.persistence.*; 

@Entity 
@Inheritance(strategy = InheritanceType.JOINED) 
public class Element { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    @Column 
    private String type; 

    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public String getType() { 
     return type; 
    } 

    public void setType(String type) { 
     this.type = type; 
    } 
} 

每一個元素都實現看起來不同,但這個例子應該足夠:

import javax.persistence.Column; 
import javax.persistence.Entity; 

@Entity 
public class SpecializedElement1 extends Element { 

    @Column 
    private String attribute; 

    public String getAttribute() { 
     return attribute; 
    } 

    public void setAttribute(String attribute) { 
     this.attribute = attribute; 
    } 

} 

我們用傑克遜和一個典型的控制器動作看起來像這樣:

@RequestMapping(value = "/createElement", method = RequestMethod.POST) 
@ResponseBody 
public HashMap<String, Object> create(@RequestBody Element element) { 
    HashMap<String, Object> response = new HashMap<String, Object>() 
    response.put("element", element); 
    response.put("status", "success"); 
    return response; 
} 

一個典型的請求主體看起來是這樣的:

{ 
    "type": "constantStringForSpecializedElement1" 
    "text": "Bacon ipsum dolor sit amet cow bacon drumstick shankle ham hock hamburger." 
} 

正如您將看到的:由於Jackson不知道如何將此對象映射到SpecializedElement1,因此這不起作用。

問題是:我該如何做這項工作?

回答

1

我想通了。這就是解決方案:

@Entity 
@Inheritance(strategy = InheritanceType.JOINED) 
@JsonTypeInfo(
    // We use the name defined in @JsonSubTypes.Type to map a type to its implementation. 
    use = JsonTypeInfo.Id.NAME, 
    // The information that stores the mapping information is a property. 
    include = JsonTypeInfo.As.PROPERTY, 
    // The property is called "type". 
    property = "type" 
) 
@JsonSubTypes({ 
     @JsonSubTypes.Type(value = SpecializedElement1.class, name = "specializedElement1"), 
     @JsonSubTypes.Type(value = SpecializedElement1.class, name = "specializedElement2") 
}) 
public class Element { 
    // .... 
} 

此控制器操作按預期工作...

@RequestMapping(value = "/create", method = RequestMethod.POST) 
@ResponseBody 
public Map<String, Object> create(@RequestBody Element element) { 
    if (element == null) { 
     // Return an error response. 
    } 
    try { 
     return elementService.update(element); 
    } catch (Exception e) { 
     // Return an error response. 
    } 
} 

...這個請求:

POST /create/ 
... more headers ... 
Content-Type: application/json 


{ 
    "type": "specializedElement1" 
}