java - 序列化已经有 POJO 的 id (java.lang.String)

标签 java json spring serialization jackson

我使用 spring 框架 4.2.5 + jacksonjson 2.7.5 序列化并发送给客户端的两个实体。我的实体如下:

@Entity
@Table(name = "entrada")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="idEntrada")
public class EntradaTest implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@Column(name = "id_entrada", unique = true, nullable = false)
private String idEntrada;

@Column(nullable = false, length = 5)
private String codigo;

private Integer recibidos;

@ManyToOne
@JsonIdentityReference(alwaysAsId = true)
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "idEmpleado", scope = Empleado.class)
@JoinColumn(name = "id_pesador_bruto")
private Empleado pesadorBruto;

@ManyToOne
@JsonIdentityReference(alwaysAsId = true)
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "dEmpleado", scope = Empleado.class)
@JoinColumn(name = "id_pesador_tara")
private Empleado pesadorTara;

@ManyToOne
@JsonIdentityReference(alwaysAsId = true)
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "idEmpleado", scope = Empleado.class)
@JoinColumn(name = "id_representante_bruto")
private Empleado representanteBruto;

@ManyToOne
@JsonIdentityReference(alwaysAsId = true)
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "idEmpleado", scope = Empleado.class)
@JoinColumn(name = "id_representante_tara")
private Empleado representanteTara;

@ManyToOne
@JoinColumn(name = "id_oficina", nullable = false)
private Entidad oficina;
}

@Entity
@Table(name = "empleado")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="idEmpleado", scope = Empleado.class)
class Empleadoest implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@Column(name = "id_empleado", unique = true, nullable = false)
private String idEmpleado;

@Column(nullable = false, length = 125)
private String nombre;

@OneToMany(mappedBy = "pesadorBruto")
private Set<Entrada> entradasPesadorBruto;

@OneToMany(mappedBy = "pesadorTara")
private Set<Entrada> entradasPesadorTara;

@OneToMany(mappedBy = "representanteBruto")
private Set<Entrada> entradasRepresentanteBruto;

@OneToMany(mappedBy = "representanteTara")
private Set<Entrada> entradasRepresentanteTara;
}

我的 REST 服务端点是

@RequestMapping(value = "/entradas/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Entrada> getEntrada(@PathVariable("id") String idEntrada) {
Entrada entrada = entradaService.get(idEntrada);
if (entrada == null) {
return new ResponseEntity<Entrada>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<Entrada>(entrada, HttpStatus.OK);
}

@RequestMapping(value = "/entradas/", method = RequestMethod.POST)
public ResponseEntity<Void> createEntrada(@RequestBody Entrada entrada, UriComponentsBuilder ucBuilder) {

entradaService.save(entrada);

HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/entradas/{id}").buildAndExpand(entrada.getIdEntrada()).toUri());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}

我发送给客户端的序列化数据如下:

{
"idEntrada": "e375ecf9-dabd-4c76-8813-0679818f9590",
"codigo": "378-2",
"recibidos": 0,
"pesadorBruto": "0c23c490-a54a-495d-9447-dc6227520646",
"pesadorTara": "874dfe26-11cb-48e4-916e-bf8a83187dcb",
"representanteBruto": "5fb567af-805a-40dc-84bc-8f6038d8cd2f",
"representanteTara": "5fb567af-805a-40dc-84bc-8f6038d8cd2f",
"oficina": {
"idEntidad": "f3964add-3ae8-4392-bafc-cffb9643ec15",
"nombre": "O.P.C.",
},
}

但是当我尝试如下将数据发送回服务器以创建一个新实体时

{
"idEntrada":"e375ecf9-dabd-4c76-8813-0679818f9590",
"codigo":"378-2",
"pesadorBruto":{
"idEmpleado":"0c23c490-a54a-495d-9447-dc6227520646",
"nombre":"J. CABRERA",
},
"pesadorTara":{
"idEmpleado":"874dfe26-11cb-48e4-916e-bf8a83187dcb",
"nombre":"L. A. DELGADO",
},
"representanteBruto":{
"idEmpleado":"5fb567af-805a-40dc-84bc-8f6038d8cd2f",
"nombre":"C. MARQUEZ",
},
"representanteTara":{
"idEmpleado":"5fb567af-805a-40dc-84bc-8f6038d8cd2f",
"nombre":"C. MARQUEZ",
},
"oficina":{
"idEntidad":"f3964add-3ae8-4392-bafc-cffb9643ec15",
"nombre":"O.P.C.",
},
}

jackson 失败了:

Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException:
Could not read document: Already had POJO for id (java.lang.String)
[[ObjectId: key=5fb567af-805a-40dc-84bc-8f6038d8cd2f,
type=com.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGenerator,
scope=lt.ciader.model.Empleado]]
(through reference chain: lt.ciader.model.Entrada["representanteTara"]->lt.ciader.model.Empleado["idEmpleado"]);
nested exception is com.fasterxml.jackson.databind.JsonMappingException:
Already had POJO for id (java.lang.String)
[[ObjectId: key=5fb567af-805a-40dc-84bc-8f6038d8cd2f,
type=com.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGenerator,
scope=lt.ciader.model.Empleado]]
(through reference chain: lt.ciader.model.Entrada["representanteTara"]->lt.ciader.model.Empleado["idEmpleado"])

我知道 representanteTara 与 representateBruto 相同,但根据我的模型,它可以是相同的工作,甚至 pesadorTara 和 PesadorBruto 也是。

当我使用不同的 empleados 发送数据时,我的服务会毫无问题地获取数据并对其进行序列化。 我用谷歌搜索找到解决方案,但找不到对我有帮助的答案。我回顾:

JsonMappingException: Already had POJO for id

Jackson Already had POJO for id

Spring Rest error the second time that saves Object with child properties that references the same father the second time: Already had POJO for id

https://groups.google.com/forum/#!topic/jackson-user/TSloBi1C_qk

https://github.com/edwinquaihoi/jsonidentitymanytomany/issues/1

https://github.com/FasterXML/jackson-databind/issues/266

我做错了什么。我该如何解决这个问题。

最佳答案

经过多次测试,我找到了解决方案。问题是 jackson 失败了,因为同一个实体出现了两次。解决方案是在第二个实例中只发送普通 ID,而不是包装在对象中:

{
"idEntrada":"e375ecf9-dabd-4c76-8813-0679818f9590",
"codigo":"378-2",
"pesadorBruto":{
"idEmpleado":"0c23c490-a54a-495d-9447-dc6227520646",
"nombre":"J. CABRERA",
},
"pesadorTara":{
"idEmpleado":"874dfe26-11cb-48e4-916e-bf8a83187dcb",
"nombre":"L. A. DELGADO",
},
"representanteBruto":{
"idEmpleado":"5fb567af-805a-40dc-84bc-8f6038d8cd2f",
"nombre":"C. MARQUEZ",
},

"representanteTara": "5fb567af-805a-40dc-84bc-8f6038d8cd2f",

"oficina":{
"idEntidad":"f3964add-3ae8-4392-bafc-cffb9643ec15",
"nombre":"O.P.C.",
},
}

关于java - 序列化已经有 POJO 的 id (java.lang.String),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42558927/

相关文章:

java - 带有 Unicode 的正则表达式模式不进行大小写折叠

java - 在 Linux (Ubuntu) 上安装 SQL Developer 的问题

c# - 将 java applet 嵌入到 C# 桌面应用程序中

java - Java 中随机方法对数字进行排序

java - Scala中获取Json头节点值

javascript - 选择标签未以正确的形式返回输入数据( Angular )

java - 如何使用 asynctask json 添加 pojo

java - 具有多模块项目的 Liquibase

spring - 使用 RabbitMQ 的 Spring Cloud Stream 消费者的多个 bindingRoutingKey

java - 如何使嵌入tomcat的spring boot应用程序能够在weblogic上运行?