JavaREST服务接受POJO,但字段总是空的

JavaREST服务接受POJO,但字段总是空的,java,json,rest,Java,Json,Rest,我有一个使用POJO的REST服务。方法如下: @POST @Path("terminate") @Produces({"application/xml", "application/json"}) @Consumes({"application/xml", "application/json"}) public TerminateActorCommand terminateActor(TerminateActorCommand cmd) { System.out.println("Ru

我有一个使用POJO的REST服务。方法如下:

@POST
@Path("terminate")
@Produces({"application/xml", "application/json"})
@Consumes({"application/xml", "application/json"})
public TerminateActorCommand terminateActor(TerminateActorCommand cmd) {
    System.out.println("Running terminate: " + cmd);
    Query query = em.createNamedQuery("Actor.terminate");
    query.setParameter("eid", cmd.getActorEid());
    query.executeUpdate();
    return cmd;
}
这是POJO

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author mike
 */
@XmlRootElement
public class TerminateActorCommand {

    String actorEid;
    String terminatorEid;
    String reason;
    Date effectiveTerminationDate;

    public TerminateActorCommand() {
    }

    @JsonCreator
    public TerminateActorCommand(@JsonProperty("actorEid") String actorEid, @JsonProperty("terminatorEid") String terminatorEid,
            @JsonProperty("reason") String reason) { //, @JsonProperty("effectiveTerminationDate") Date effectiveTerminationDate) {
        this.actorEid = actorEid;
        this.terminatorEid = terminatorEid;
        this.reason = reason;
        //this.effectiveTerminationDate = effectiveTerminationDate;
    }

    public CommandType getCommandType() {
        return CommandType.TERMINATE_ACTOR;
    }

    public String getActorEid() {
        return actorEid;
    }

    public String getTerminatorEid() {
        return terminatorEid;
    }

    public String getReason() {
        return reason;
    }

    public Date getEffectiveTerminationDate() {
        return effectiveTerminationDate;
    }

    @Override
    public String toString() {
        return "TerminateActorCommand{" + "actorEid=" + actorEid + ", terminatorEid=" + terminatorEid + ", reason=" + reason + ", effectiveTerminationDate=" + effectiveTerminationDate + '}';
    }
}
当我用CURL来称呼它时:

curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"actorEid":"mb995a", "terminatorEid":"mb995a","reason":"testing"}' http://127.0.0.1:8080/actor-service/webresources/net.mikeski.auth.entities.actors/terminate
我得到返回值并看到print语句,但是TerminationCommand的字段都是null。我得到一个实例化的对象,但是我发送的JSON没有填充到对象上

为什么

以下是输出:

信息:正在运行terminate:TerminateActorCommand{actorEid=null,TerminateOreId=null,reason=null,effectiveTerminationDate=null}


我已经浏览了您问题中包含的所有代码,并提出了一些建议:

TerminateActorCommand
POJO中,将
@JsonProperty
注释添加到与JSON属性匹配的成员中(存在属性访问器方法,但缺少mutator方法可能会令人困惑):

如果添加
@JsonProperty
无法解决您的问题,请检查
TerminateActorCommand
类中当前定义的无参数构造函数。当您使用Jackson
@JsonCreator
注释时,不需要定义无参数构造函数,但是如果Jackson在反序列化过程中找不到合适的匹配项,它将退回到使用无参数构造函数。我的猜测是,无参数构造函数是JSON反序列化过程中当前调用的构造函数(因此是
null
属性值),因此我建议删除该构造函数,或者,如果需要(可能在代码的其他部分),在无参数构造函数中添加
System.out.println
,因此,当Jackson执行JSON反序列化时,您将确定是否调用了该构造函数


您的
cURL
命令
-d
有效负载规范中的第一个和第二个属性之间也存在不必要的空格,这不会导致问题,但删除该空格将排除可能出现的问题。

我已经浏览了您问题中包含的所有代码,我有一些建议:

TerminateActorCommand
POJO中,将
@JsonProperty
注释添加到与JSON属性匹配的成员中(存在属性访问器方法,但缺少mutator方法可能会令人困惑):

如果添加
@JsonProperty
无法解决您的问题,请检查
TerminateActorCommand
类中当前定义的无参数构造函数。当您使用Jackson
@JsonCreator
注释时,不需要定义无参数构造函数,但是如果Jackson在反序列化过程中找不到合适的匹配项,它将退回到使用无参数构造函数。我的猜测是,无参数构造函数是JSON反序列化过程中当前调用的构造函数(因此是
null
属性值),因此我建议删除该构造函数,或者,如果需要(可能在代码的其他部分),在无参数构造函数中添加
System.out.println
,因此,当Jackson执行JSON反序列化时,您将确定是否调用了该构造函数


您的
cURL
命令
-d
有效负载规范中的第一个和第二个属性之间也存在不必要的空格,这不会导致问题,但是删除该空格将排除这一可能的问题。

我认为属性没有设置,因为您的字段/设置器没有标记为
@JsonProperty
。即使您在参数化构造函数中将它们标记为json属性,用注释标记这些字段或setter应该会有帮助,因为您的库/框架可能没有使用arg构造函数实例化对象,然后在创建的对象上惰性地设置属性。

我认为属性没有设置,因为您的字段/setter没有标记为
@JsonProperty
。即使您已在参数化构造函数中将这些字段或setter标记为json属性,但将这些字段或setter标记为注释也会有所帮助,因为您的库/框架可能没有使用arg构造函数来实例化对象,然后在创建的对象上惰性地设置属性。

。正如预期的那样,我添加了您的注释,没有任何区别。我添加了setter,并且使用了无参数构造函数。当我像我的原始代码一样添加@JsonCreator构造函数并去掉其他构造函数时,我得到了
MessageBodyReader not found for media type=application/json
。我希望这个对象是不可变的。如何做到这一点?构造函数上的
@JsonCreator
注释(没有setter方法)是保持不变性的正确方法。您使用的是什么版本的Jackson(
Jackson core
Jackson annotations
、以及
Jackson databind
)?您的项目是否包含一个单独的Jackson配置文件?这是正确的,我不需要删除默认构造函数,只创建了一个带有我想要设置的字段的@JsonCreator标记的构造函数,它可以工作。这很有趣。正如预期的那样,我添加了您的注释,没有任何区别。我添加了setter,并且使用了无参数构造函数。当我像我的原始代码一样添加@JsonCreator构造函数并去掉其他构造函数时,我得到了
MessageBodyReader not found for media type=application/json
。我希望这个对象是不可变的。如何做到这一点?构造函数上的
@JsonCreator
注释(没有setter方法)是保持不变性的正确方法。您使用的是什么版本的Jackson(
Jackson core
Jackson annotations
、以及
Jackson databind
)?您的项目是否包含一个单独的Jackson配置文件?这是正确的,我不需要去掉默认的cons

@JsonProperty String actorEid;
@JsonProperty String terminatorEid;
@JsonProperty String reason;