带有Spring MVC的Jackson重复嵌套对象而不是反序列化 [英] Jackson with Spring MVC duplicate nested objects not deserializing

查看:171
本文介绍了带有Spring MVC的Jackson重复嵌套对象而不是反序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将以下POJO转换为中的JSON @RestController

I am trying to Convert following POJO to a JSON in @RestController:

@Entity
@Table(name="user_location")
@NamedQuery(name="UserLocation.findAll", query="SELECT u FROM UserLocation u")
public class UserLocation implements Serializable {
    private static final long serialVersionUID = 1L;

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

    private String addr1;

    private String addr2;

    private String landmark;

    private BigDecimal lat;

    private BigDecimal lng;

    private String zipcode;

    //bi-directional many-to-one association to City
    @ManyToOne
    private City city;

    //bi-directional many-to-one association to State
    @ManyToOne
    private State state;

    public UserLocation() {
    }

    //Getter - Setters

}

嵌套的City.java如下:

Nested City.java is as follow:

@Entity
@NamedQuery(name="City.findAll", query="SELECT c FROM City c")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property="@id", scope = City.class)
public class City implements Serializable {
    private static final long serialVersionUID = 1L;

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

    private String name;

    //bi-directional many-to-one association to State
    @ManyToOne
    @JsonIgnore
    private State state;

    //bi-directional many-to-one association to UserLocation
    @OneToMany(mappedBy="city")
    @JsonIgnore
    private List<UserLocation> userLocations;

    public City() {
    }

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @JsonProperty("state")
    public State getState() {
        return this.state;
    }

    public void setState(State state) {
        this.state = state;
    }


    public List<UserLocation> getUserLocations() {
        return this.userLocations;
    }

    public void setUserLocations(List<UserLocation> userLocations) {
        this.userLocations = userLocations;
    }

    public UserLocation addUserLocation(UserLocation userLocation) {
        getUserLocations().add(userLocation);
        userLocation.setCity(this);

        return userLocation;
    }

    public UserLocation removeUserLocation(UserLocation userLocation) {
        getUserLocations().remove(userLocation);
        userLocation.setCity(null);

        return userLocation;
    }

}

另一个嵌套类State.java是如下所示:

Another nested class State.java is as follow:

@Entity
@NamedQuery(name="State.findAll", query="SELECT s FROM State s")
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property="@id", scope = State.class)
public class State implements Serializable {
    private static final long serialVersionUID = 1L;

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

    private String name;

    //bi-directional many-to-one association to City
    @OneToMany(mappedBy="state")
    @JsonIgnore
    private List<City> cities;

    //bi-directional many-to-one association to UserLocation
    @OneToMany(mappedBy="state")
    @JsonIgnore
    private List<UserLocation> userLocations;

    public State() {
    }

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<City> getCities() {
        return this.cities;
    }

    public void setCities(List<City> cities) {
        this.cities = cities;
    }

    public City addCity(City city) {
        getCities().add(city);
        city.setState(this);

        return city;
    }

    public City removeCity(City city) {
        getCities().remove(city);
        city.setState(null);

        return city;
    }

    public List<UserLocation> getUserLocations() {
        return this.userLocations;
    }

    public void setUserLocations(List<UserLocation> userLocations) {
        this.userLocations = userLocations;
    }

    public UserLocation addUserLocation(UserLocation userLocation) {
        getUserLocations().add(userLocation);
        userLocation.setState(this);

        return userLocation;
    }

    public UserLocation removeUserLocation(UserLocation userLocation) {
        getUserLocations().remove(userLocation);
        userLocation.setState(null);

        return userLocation;
    }

}

从UserLocation.java转换的JSON如下:

The JSON converted from UserLocation.java is as follow:

{
    id: 1,
    addr1: "11905 Technology",
    addr2: "Eden Prairie",
    landmark: null,
    lat: null,
    lng: null,
    zipcode: "55344",
    city: {
        @id: 1,
        id: 2,
        name: "Westborough",
        state: {
            @id: 1,
            id: 2,
            name: "MA"
        }
    },
    state: 1
}

如您所见, State 对象将作为 city 。但外部('UserLocation 的属性只显示对象的ID。我需要具有与 city`相同的对象,而不仅仅是id。

As you can see, the State object is coming as a whole object inside city. But outer state (property of 'UserLocationis showing just an id ofStateobject. I need to have a samestateobject as that ofcity` instead of just id.

我对JackSon api相对较新。请建议我应该采用哪种方法来达到这个要求。

I am relatively new to JackSon api. Please advice which approach I should follow to achieve this requirement.

谢谢

推荐答案

这就是杰克逊设计JsonIdentityInfo注释逻辑的方法。

This is how jackson designed JsonIdentityInfo annotation logic.

 * Annotation used for indicating that values of annotated type
 * or property should be serializing so that instances either
 * contain additional object identifier (in addition actual object
 * properties), or as a reference that consists of an object id
 * that refers to a full serialization. In practice this is done
 * by serializing the first instance as full object and object
 * identity, and other references to the object as reference values.

杰克逊将首次运行完整序列化,只有当第二次找到该对象时才会序列化。

Jackson will run the full serialization first time and only id will be serialized when it find that object second time.

所以,有两种方法可以解决它:

So, there is two ways how you can fix it:

1)你可以简单地删除@JsonIdentityInfo注释,杰克逊会按预期序列化对象,但它会删除来自响应的@id字段。这可能很好,因为你仍然会有'id'属性。

1) you can simple remove the @JsonIdentityInfo annotation and Jackson will serialize object as you expected but it will remove the @id field from the response. This is probably fine because you still will have 'id' property.

2)我觉得你可以简单地重构你的对象并删除一些引用。我会说无论如何做这些改变都是好的。首先,您可以从UserLocation删除对State的引用。我会说,由于State附加到City,因此没有必要将State设置为userLocation类。
通过执行此操作,您将从City访问State并解决您的问题。
此外,我还会从City类和State类中删除对userLocations列表的引用。

2) I feel like you can simply restructure your objects and delete some references. I would say it is good to do these changes anyway. First of all you can delete reference to the State from UserLocation. I would say that it is not necessary to have the State in userLocation class because of the State is attached to the City. By doing this you will access State from the City and your problem is solved. Also I would delete the reference to the list of userLocations from the City class as well as from State class.

它将如下所示:

UserLocation有City且没有州。

UserLocation has City and doesn't have State.

城市有州且没有userLocations

City has State and doesn't have userLocations

州没有userLocations和城市。

State doesn't have userLocations as well as cities.

希望这会有所帮助

这篇关于带有Spring MVC的Jackson重复嵌套对象而不是反序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆