Java JAX-RS使用@XmlIDREF解卷

Java JAX-RS使用@XmlIDREF解卷,java,json,jax-rs,unmarshalling,Java,Json,Jax Rs,Unmarshalling,我已经研究这个问题好几个小时了,可能很简单,但我再也不明白了: 我有一个实体(Param),它通过jax-rs呈现为json。该实体引用另一个实体(步骤)。 在编写/读取json时,我不想看到整个step实体,只想看到它的id,因此我使用以下代码: @Entity @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Param implements Serializable { private static fin

我已经研究这个问题好几个小时了,可能很简单,但我再也不明白了:

我有一个实体(Param),它通过jax-rs呈现为json。该实体引用另一个实体(步骤)。 在编写/读取json时,我不想看到整个step实体,只想看到它的id,因此我使用以下代码:

@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Param implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
long id;
@Column(name = "KEYNAME")
String key;
String value;
@XmlIDREF
Step step;  
}
非常适合编组

因此,任何GET请求都会显示以下内容:

{id: 1,
key: "a",
value: "b",
step: 53
}
但当我向服务器发布一些参数时,它无法将数字id映射回step实体

我需要为解组器提供自定义IDResolver。但是如何配置解组器????Jax-rsservlet正在为我进行编组。我的代码如下所示:

@Path("param")
public class ParamRepresentation {

  /**
   * Retrieves representation of an instance of ParamRepresentation
   * @return an instance of Param
   */
  @GET
  @Produces("application/json")
  @Path("{ID}")
  public Param getJson(@PathParam("ID") long id) {
    return (Param) ctr.find(id, Param.class);
}


@PUT
@Path("{ID}")
@Consumes("application/json")
@Produces("application/json")
public SuccessMessage updateStep(@PathParam("ID") long id, Param p) {
    ctr.update(p);
    ParamSuccessMessage sm = new ParamSuccessMessage();
    sm.setSuccess(true);
    sm.setParam(p);
    return sm;
}
}

那么如何配置解组器?????

我认为您误解了IDREF在XML模式中的用途。它允许您在同一文档中引用另一个标记为ID的元素(即,在JAXB中使用
@XmlID
注释)。你不能用它来指代世界其他地方的ID;为此,您将使用URI(可能带有片段标识符部分)。要在JAXB中执行这些操作,可以使用:

@XmlElement    // You might be able to omit this part; it's here for clarity
@XmlSchemaType(name = "anyURI")
public URI exampleField;

然后,您需要确定URI是否引用您知道的内容(即解析URI并查看它是否指向您自己),并处理片段标识符。或者做一个更常见的技巧,只使用一个字符串,而不用担心尝试在绑定层中神奇地连接所有内容。(这在实践中效果相当好。)

我使用Jersey和xml表示做了类似的事情。我使用xml适配器在完整的子元素和部分(仅id)元素之间对称映射

我会在Param实体中对Step实体进行如下注释:

//javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter
@XmlJavaTypeAdapter(PartialStepEntityAdapter.class)
Step step
然后,您需要同时定义分部步骤实体和适配器。
PartialStep
将与原始步骤类相同,但只包含id字段

当编组时,
partialsteppentityadapter
会将
步骤
映射到
PartialStep
,而当解编组时,
PartialStep
会映射到
步骤

//javax.xml.bind.annotation.adapters.XmlAdapter
public class PartialStepEntityAdapter extends XmlAdapter<PartialStep, Step> {

    @Override
    public Step unmarshal(PartialStep partialStep) throws Exception {
        Step step = new Step();
        step.setId(partialStep.getId());

        return step;
    }

    @Override
    public PartialStep marshal(Step step) throws Exception {
        PartialStep partialStep= new PartialStep();
        partialStep.setId(step.getId());

        return partialStep;
    }
}
//javax.xml.bind.annotation.adapters.XmlAdapter
公共类PartialStepEntityAdapter扩展了XmlAdapter{
@凌驾
公共步骤解组(PartialStep PartialStep)引发异常{
步骤=新步骤();
setId(partialStep.getId());
返回步骤;
}
@凌驾
public PartialStep封送处理(步骤)引发异常{
PartialStep PartialStep=新的PartialStep();
partialStep.setId(step.getId());
返回partialStep;
}
}

希望能有所帮助。

问得好。你已经展示了你所做的尝试,并清楚地解释了你认为事情会在哪里失控。请投票。+1-@Florian-这里有一个链接,指向我的一篇博客文章,展示了Donal Fellows在回答有关IDREF的问题时所说的话:当然,在解组后,你必须找到自己的方法来填充实体的其余部分。