Java jackson - 不要序列化惰性对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25906985/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hymanson - do not serialize lazy objects
提问by villager
I have an entity:
我有一个实体:
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column
private String title;
@OneToMany(fetch = FetchType.LAZY, mappedBy = ("movie"),cascade = CascadeType.ALL)
private List<Genre> genre;
}
Then I have a controller whose purpose is to retrieve books, my problem is that, the genre field is being included in the json response of my controller. Any way I can exclude those fields that are lazy loaded when Hymanson serializes the object?
然后我有一个控制器,其目的是检索书籍,我的问题是,流派字段包含在我的控制器的 json 响应中。有什么办法可以排除那些在 Hymanson 序列化对象时延迟加载的字段?
This is the configuration of my ObjectMapper:
这是我的 ObjectMapper 的配置:
Hibernate4Module hm = new Hibernate4Module();
hm.configure(Hibernate4Module.Feature.FORCE_LAZY_LOADING, false);
registerModule(hm);
configure(SerializationFeature.INDENT_OUTPUT, true);
Thanks!
谢谢!
I can't mark it as JsonIgnore, as it will be forever out of the serialization box. There will be times where I will need to retrieve the genres along with the book, and by then I will use "fetch join" on my query so it will not be null.
我不能将它标记为 JsonIgnore,因为它将永远在序列化框之外。有时我需要随书一起检索流派,到那时我将在我的查询中使用“fetch join”,这样它就不会为空。
采纳答案by Davide Rossi
You can do this with the Hymanson @JsonInclude
annotation.
您可以使用 Hymanson@JsonInclude
注释执行此操作。
According to the latest version's javadoc (2.4 right now)you can specify with a simple annotation if to include or not the annotated property if the field value is null or empty.
根据最新版本的 javadoc(现在是 2.4),如果字段值为 null 或为空,您可以使用简单的注释指定是否包含带注释的属性。
By default, it's JsonInclude.Include.ALWAYS
, and this means that even if your lazily not-loaded values are null, Hymanson does include the property.
默认情况下,它是JsonInclude.Include.ALWAYS
,这意味着即使您延迟加载的值为 null,Hymanson 也会包含该属性。
Specifying to don't include empty or null values can significantly reduce the size of the JSON response, with all the benefits included..
指定不包含空值或 null 值可以显着减小 JSON 响应的大小,包括所有好处。
If you want to change this behavior, you can add the annotation at class-level or single property/getterMethod level.
如果要更改此行为,可以在类级别或单个属性/getterMethod 级别添加注释。
Try to add the following annotations to the fields you don't want to include if empty:
尝试将以下注释添加到您不想包含的字段(如果为空):
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@OneToMany(fetch = FetchType.LAZY, mappedBy = ("movie"),cascade = CascadeType.ALL)
private List<Genre> genre;
回答by Jay
Maybe this is related to a known issue about lazy loading.
也许这与关于延迟加载的已知问题有关。
I don't use Hymanson-datatype-hibernate, but what I've done to solve the same problem is to get the persistent collection out of the picture by using a DTO instead of serializing a Hibernate object directly. Tools like Dozer can help you out with that. Alternatively, there's a small utilityI wrote to do mappings like this.
我不使用 Hymanson-datatype-hibernate,但我为解决同样的问题所做的是通过使用 DTO 而不是直接序列化 Hibernate 对象来从图片中获取持久集合。Dozer 之类的工具可以帮助您解决这个问题。或者,我编写了一个小实用程序来进行这样的映射。
If you just want to experiment with what a DTO could look like, you can replace the unloaded persistent collection with a regular empty collection, like books.setGenre(new ArrayList<>()); Unfortunately I don't know of a way to tell if a lazily loaded object has been loaded or not, so you can't do this reassignment automatically. The places where you replace persistent collections would need to be determined by you on a case by case basis.
如果你只是想尝试一下 DTO 的样子,你可以用一个普通的空集合替换卸载的持久集合,比如 books.setGenre(new ArrayList<>()); 不幸的是,我不知道有什么方法可以判断延迟加载的对象是否已加载,因此您无法自动进行重新分配。您需要根据具体情况确定替换持久集合的位置。
回答by Ricardo Veguilla
You can use Hymanson's JSON Filter Feature:
您可以使用Hymanson 的 JSON 过滤器功能:
@Entity
@JsonFilter("Book")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column
private String title;
@OneToMany(fetch = FetchType.LAZY, mappedBy = ("movie"),cascade = CascadeType.ALL)
private List<Genre> genre;
}
@Entity
@JsonFilter("Genre")
public class Genre {
...
}
Then in the Controller you specify what to filter:
然后在控制器中指定要过滤的内容:
@Controller
public class BookController {
@Autowired
private ObjectMapper objectMapper;
@Autowird
private BookRepository bookRepository;
@RequestMapping(value = "/book", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public ResponseEntity<String> getBooks() {
final List<Book> books = booksRepository.findAll();
final SimpleFilterProvider filter = new SimpleFilterProvider();
filter.addFilter("Book", SimpleFilterProvider.serializeAllExcept("Genre");
return new ResponseEntity<>(objectMapper.writer(filter).writeValueAsString(books), HttpStatus.OK)
}
}
In this way, you can control when you want to filter the lazy relation at runtime
这样就可以控制运行时什么时候过滤lazy关系了