我正在尝试使用Spring boot/Spring RestController后端从AngularJS前端POST到http://localhost:9095/translators。
我可以执行GET,响应如下所示:
[{"userId":1,"firstName":"John","lastName":"Doe","emailId":"john.doe@inc.com","languages":[{"languageId":1,"languageCode":"gb","source":true}],"translations":[{"translationId":3,"sourceId":1,"sourceText":"Hello","targetId":null,"targetText":null,"translationStatus":"DUE"}],"userType":"TRANSLATOR"}
当我发布下面的json时,我得到了error响应
- 开机自检数据:*
{
firstName: "zen",
lastName: "cv",
emailId: "email",
userType: "TRANSLATOR",
languages : [{languageId:1,languageCode:"gb",source:true}]
}
- 发生错误:*
{
timestamp: 1422389312497
status: 415
error: "Unsupported Media Type"
exception: "org.springframework.web.HttpMediaTypeNotSupportedException"
message: "Content type 'application/json' not supported"
path: "/translators"
}
我已经确保我的控制器有正确的Mediatype注解。
@RestController
@RequestMapping("/translators")
public class TranslatorController {
@Autowired
private UserRepository repository;
@RequestMapping(method = RequestMethod.GET)
public List findUsers() {
return repository.findAll();
}
@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
public User findUser(@PathVariable Long userId) {
return repository.findOne(userId);
}
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public User addTranslator(@RequestBody User user) {
//translation.setTranslationId(null);
return repository.saveAndFlush(user);
}
@RequestMapping(value = "/{translatorId}", method = RequestMethod.PUT)
public User updateTranslation(@RequestBody User updatedUser, @PathVariable Long userId) {
//updatedTranslation.setTranslationId(translationId);
return repository.saveAndFlush(updatedUser);
}
@RequestMapping(value = "/{translatorId}", method = RequestMethod.DELETE)
public void deleteTranslation(@PathVariable Long translationId) {
repository.delete(translationId);
}
}
经过一些研究,并通过查看日志输出,我意识到这是一个误导性的错误消息,问题实际上是在序列化/反序列化Json时发生的
在日志文件中,我发现
2015年01月27日21:08:32.488警告15152 --- [nio-9095-exec-1]. c. j.MapJackson2 Http消息转换器:无法评估类型[简单类型,类别User]的还原序列化:异常错误:无法处理托管/向后引用“defaultReference”:反向引用类型(java.util.List)与托管类型(User)不兼容
这是我的类User和类Translation(getter、setter、constructor等,为了简洁起见省略了)
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
@Column(name = "user_id")
private long userId;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "email_id")
private String emailId;
@ManyToMany
@JoinTable(name = "languages_users", joinColumns = { @JoinColumn(name = "user_id")},
inverseJoinColumns = {@JoinColumn(name = "lang_id")})
@JsonManagedReference
private List<Language> languages = new ArrayList<Language>();
@OneToMany(mappedBy = "translator", fetch = FetchType.EAGER)
@JsonManagedReference
private List<Translation> translations;
@Enumerated(EnumType.STRING)
private UserType userType;
}
@Entity
@Table(name = "translations")
public class Translation {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name = "translation_id")
private Long translationId;
@Column(name = "source_lang_id")
private Long sourceId;
@Column(name = "source_text")
private String sourceText;
@Column(name = "target_lang_id")
private Long targetId;
@Column(name = "target_text")
private String targetText;
@Enumerated(EnumType.STRING)
@Column(name = "status")
private TranslationStatus translationStatus;
@ManyToOne
@JoinColumn(name = "translator_id")
@JsonBackReference
private User translator;
}
我的问题是这样的:如何正确设置上述实体的JsonManagedReference和JsonBackReference?我看了doc.,根据错误信息,我无法判断出这里的错误
8条答案
按热度按时间l0oc07j21#
正如@Sharppoint在评论中所说,我通过删除
@JsonManagedReference
但保留@JsonBackReference
来解决地雷问题。gjmwrych2#
对于那些有疑问的人,另一种方法是使用fasterxml的JsonIdentityInfo,并使用以下内容对类进行注解:
3df52oht3#
我通过去掉JsonManagedReference和JsonBackReference并将其替换为JsonIdentityInfo来解决此问题
s6fujrry4#
您需要
@ResponseBody
注解,如下所示:mutmk8jj5#
可以通过移除基类中的
JsonManagedReference
来解决此问题。@JsonBackReference
在从控制器获取/发布数据时执行停止无限递归的工作。我假设您的Language类中有多个
@JsonBackReference
,所以当您发送包含两个类的用户数据时,spring无法反序列化对象并相应地Map它。您只需从Translation/Language类中删除其中一个
@JsonBackReference
,并将其替换为@JsonIgnore
/@JsonIdentityInfo
即可解决此问题。这样,您实际上是在进行相同的Map,但相反,您排除了多个
@JsonBackReference
到基类的可能性,这被明确指出为导致415 Unsupported media type exception
的错误。rdlzhqv96#
我遇到了同样的错误,我解决了删除所有注解@JsonBackReference和@JsonManagedReference的问题,然后我将@JsonIdentityInfo放在所有具有关系的类中。
pkmbmrz77#
另一个解决这个问题的好方法是使用
@JsonView
。其思想是用一个视图名称来标记控制器,然后标记希望为该视图显示的属性。明确地说,不要向调用视图公开 backreferenced 属性。下面是一个极其简化的示例:假设你有这样一个一对一的关系,这会产生一个循环引用。
现在,您可以为它们创建视图,几乎与处理
@JsonIgnore
和@JsonProperty
的方法相同。步骤1.创建可用于标记控制器的任意空接口。
第2步:标记要向视图公开的属性(在任何相关/引用类中),也使用
@JsonView
注解。ozxc1zmp8#
我通过添加@JsonIgnore解决了一个类似的问题