2013-03-11 46 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" 
}