2014-12-10 4 views
0

서버 관계를보기 위해 RESTful 서비스를 구축 중입니다 (서버는 다른 서버를 부모로 포함 할 수 있음). 이 서비스는 CRUD 명령에 JSON 문자열을 허용합니다. 이이 - 난 단지 부모가 아닌 부모 개체의 호스트 이름을 얻을 부모로서Jackson jsonidentityinfo 직렬화가 실패합니다.

{"hostname":"childhostname", "parent":"parenthostname"} 

가 : 사용자가이 같은 JSON 응답을 단순화받을 수 있도록

나는 내 서버 개체에 @JsonIdentityInfo@JsonIdentityReference를 사용 정확히 내가 원하는 것과 잘 작동합니다.

업데이트 명령을 역 직렬화하려고 할 때 (부모 업데이트를 시도 할 때) 내 문제가 발생합니다. 보내면

curl -i -X POST -H 'Content-Type: application/json' -d '{"parent":"parenthostname"}' http://localhost:8080/myRestService/rest/servers/childhostname 

아무 일도 일어나지 않습니다. 부모는 설정되지 않습니다. 문제는 전달 된 JSON 문자열에있다 :

{"parent":"parenthostname"} 

최대 절전 모드 2.4.4 소스 코드를 디버깅 후, 나는 내 JSON 문자열은 com.fasterxml.jackson.databind.deser.UnresolvedForwardReference: Could not resolve Object Id [parenthostname]를 생성하는 것을 발견했다. 이 예외는 Throw되지 않지만 null이 반환됩니다.

@JsonIdentityInfo과 을 제거하면이 JSON 문자열이 제대로 작동하고 부모님이 업데이트됩니다. (그렇다면 간단한 답을 잃어 버리고 무한 루프 문제가 발생합니다).

그래서 나는이 내 JSON 문자열을 조정하면 :

'{"parent":{"hostname":"parenthostname"}}' 

업데이트는 잘 작동합니다. 하지만 단순화 된 (unwrapped) 버전의 작업을하고 싶습니다. 어떤 아이디어? 어떤 힌트에 감사드립니다.

나 최대 절전 모드 4.2.4 잭슨 2.4.4

을 사용하고이 내 (간체) 서버 클래스 :

@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="hostname") 
public class Server extends A_Hardware { 

@NaturalId 
@Column(name="hostname", nullable=false, unique=true) 
private String hostname = null; 

@ManyToOne 
@JsonIdentityReference(alwaysAsId = true) 
private Server parent = null; 

@OneToMany(fetch = FetchType.LAZY, mappedBy="parent") 
@JsonIdentityReference(alwaysAsId = true) 
private Set<Server> childServers = new HashSet<Server>(); 

[...] 
// standard getters and setters 

이 내 RESTful 서비스의 업데이트 클래스 :

@POST 
    @Consumes(MediaType.APPLICATION_JSON) 
    @Produces(MediaType.TEXT_PLAIN) 
    @Path("{hostname}") 
    public Response update(@PathParam("hostname") final String hostname, JsonParser json){ 
     Server s = null; 
     ObjectMapper mapper = new ObjectMapper(); 
     mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); 
     try{ 
      s = mapper.readValue(json, Server.class); 

내 첫 질문입니다. 제 질문이 완전히 명확하지 않으면 저를 너무 심하게 판단하지 마십시오.)

+0

해결 했습니까? 나는 똑같은 것이 궁금합니다 ... – poornerd

+0

안녕 Devin! 네, 제가 해결했습니다. 아래 내 대답을 참조하십시오. 귀하의 프로젝트에 도움이되기를 바랍니다. – johnythepeanut

답변

2

해결 방법으로 다소 해결되었습니다. 원하는, 단순화 된 JSON 문자열을 전달하고 수신하려면 @JsonSetter@JsonProperty을 사용합니다.

this answer도 참조하십시오.

/** 
* JSON Helper method, used by jackson. Makes it possible to add a parent by just delivering the hostname, no need for the whole object. 
* 
* This setter enables: 
* {"parent":"hostnameOfParent"} 
* 
* no need for this: 
* {"parent":{"hostname":"hostnameOfParent"}} 
*/ 
@JsonSetter 
private void setParentHostname(String hostname) { 
    if(hostname!=null){ 
     this.parent = new Server(hostname);   
    } else { 
     this.parent = null; 
    } 
} 

/** 
* Used by jackson to deserialize a parent only with its hostname 
* 
* With this getter, only the hostname of the parent is being returned and not the whole parent object 
*/ 
@JsonProperty("parent") 
private String getParentHostname(){ 
    if(parent!=null){ 
     return parent.getHostname(); 
    } else { 
     return null; 
    } 
}