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

时间:2017-03-02 15:05:39

标签: java json spring serialization jackson

我有两个实体序列化并使用spring framework 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.",
},
}

杰克逊失败了:

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"])

我知道代表塔拉是同一个代表布鲁托,但它可以是我的模型相同的就业,甚至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

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

1 个答案:

答案 0 :(得分:1)

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

{
"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.",
},
}