序列化为JSON

时间:2016-04-08 14:26:02

标签: java json spring spring-data spring-data-rest

我们正在使用spring-data-rest 2.4.2.RELEASE(使用spring-boot,JPA / Hibernate)进行项目。 我们有一个具有这种结构的数据库模型:

table A:
  name: string
  b -> B //meaning a reference to table B
table B:
  x: number
  y: number

我们需要使用REST / JSON公开实体A:

{ "name": "myName", "position": {"x": 1, "y": 3}}

我们已经有了一个适用于Position的java类:

public class Position {

    @Column(nullable = true)
    @JsonProperty
    private Float x;
    @Column(nullable = true)
    @JsonProperty
    private Float y;
}

因此,我们使用JPA注释创建映射到数据库表的A和B类,但是我们在A中注释了一个属性position,其中@JsonProperty是一个直接访问B的getter:

@RepositoryRestResource
public interface ARepository extends JpaRepository<A, Long> {
}
@Entity
public class A {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @JsonProperty
  private Long id;

  @ManyToOne( cascade = CascadeType.ALL)
  @JsonIgnore
  private B b;

  @JsonProperty
  private String name;

  @JsonProperty
  public Position getPosition() {
      if (b == null) {
          b = new B();
      }
      return b.getPosition();
  }

  @JsonProperty
  public void setPosition(Position position) {
      if (this.b == null) {
          this.b = new B();
      }  
      this.b.setPosition(position);
  }
}

我的B对象,我不想在REST API中公开:

@Entity
public class B {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @JsonProperty
  private Long id;

  @Embedded
  @Column(nullable = true)
  private Position position;

  Position getPosition() {
      return position;
  }

  void setPosition(Position position) {
      this.position = position;
  }

}

使用这种结构,我可以毫无问题地将新对象发布到我的API:

curl -XPOST -H 'Accept: application/json' -H 'Content-type: application/json' localhost:12000/as -d '
{ "name": "aName", "position": {"x":1, "y":2}}'

这会创建一个对象:

{
  "name" : "aName",
  "position" : {
    "x" : 1.0,
    "y" : 2.0
  },
  "_links" : {
    "self" : {
      "href" : "http://127.0.0.1:12000/as/5"
    },
    "a" : {
      "href" : "http://127.0.0.1:12000/as/5"
    }
  }
}

但是当我尝试用PUT更新对象时:

curl -XPUT -H 'Accept: application/json' -H 'Content-type: application/json' localhost:12000/as/5 -d '
{"name": "aName", "position": {"x":4, "y":3}}'

我收到此错误

  

{“cause”:{“cause”:{“cause”:null,“message”:null},“message”:“无法读取有效负载!;嵌套异常是java.lang.NullPointerException”},“消息“:”无法从请求中读取类型为io.epiclabs.flex.network.A的对象!;嵌套异常是org.springframework.http.converter.HttpMessageNotReadableException:无法读取有效负载!;嵌套异常是java。 lang.NullPointerException“

调试spring-data-rest代码,我发现问题出在org.springframework.data.rest.webmvc.DomainObjectReader.doMerge第192行。

PersistentProperty<?> property = mappedProperties.getPersistentProperty(fieldName);

if (associationLinks.isLinkableAssociation(property)) {
        continue;
}

PersistentPropertyAccessor accessor = entity.getPropertyAccessor(target);
Object nested = accessor.getProperty(property);

property为null,因为A对象中没有position的映射信息(mappedProperties仅取自JPA映射信息)。

它似乎只是为了更新(PUT)而在POST中它只是采用POJO和Jackson映射信息来设置Position对象。

我的问题是:我们如何配置映射,以便在序列化/反序列化时,Jackson模块从JSONProperties注释中获取信息,而不是JPA实体信息?

我们可以在不改变数据库模型的情况下以不同的方式进行这种json映射吗?

0 个答案:

没有答案