[JavaEE] Entity中Lazy Load的属性序列化JSON时报错

时间:2021-06-28 19:10:18

The server encountered an internal error that prevented it from fulfilling this request.org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: failed to lazily initialize a collection of role: com.party.dinner.entity.User.friends, could not initialize proxy - no Session (through reference chain: com.party.dinner.entity.User["friends"]); nested exception is org.codehaus.jackson.map.JsonMappingException: failed to lazily initialize a collection of role: com.party.dinner.entity.User.friends, could not initialize proxy - no Session (through reference chain: com.party.dinner.entity.User["friends"])
    org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.writeInternal(MappingJacksonHttpMessageConverter.java:204)
    org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:179)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.writeWithMessageConverters(AnnotationMethodHandlerAdapter.java:1037)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.handleResponseBody(AnnotationMethodHandlerAdapter.java:995)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.getModelAndView(AnnotationMethodHandlerAdapter.java:944)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:441)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:428)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
   root cause org.codehaus.jackson.map.JsonMappingException: failed to lazily initialize a collection of role: com.party.dinner.entity.User.friends, could not initialize proxy - no Session (through reference chain: com.party.dinner.entity.User["friends"])
    org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218)
    org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183)
    org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140)
    org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158)
    org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
    org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610)
    org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)
    org.codehaus.jackson.map.ObjectMapper.writeValue(ObjectMapper.java:1613)

转载:http://blog.csdn.net/nomousewch/article/details/8955796

jackson在实际应用中给我们提供了一系列注解,提高了开发的灵活性,下面介绍一下最常用的一些注解

  • @JsonIgnoreProperties

此注解是类注解,作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。

  • @JsonIgnore

此注解用于属性或者方法上(最好是属性上),作用和上面的@JsonIgnoreProperties一样。

  • @JsonFormat

此注解用于属性或者方法上(最好是属性上),可以方便的把Date类型直接转化为我们想要的模式,比如@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")

  • @JsonSerialize

此注解用于属性或者getter方法上,用于在序列化时嵌入我们自定义的代码,比如序列化一个double时在其后面限制两位小数点。

  1. public class CustomDoubleSerialize extends JsonSerializer<Double> {
  2. private DecimalFormat df = new DecimalFormat("##.00");
  3. @Override
  4. public void serialize(Double value, JsonGenerator jgen,
  5. SerializerProvider provider) throws IOException,
  6. JsonProcessingException {
  7. jgen.writeString(df.format(value));
  8. }
  9. }
  • @JsonDeserialize

此注解用于属性或者setter方法上,用于在反序列化时可以嵌入我们自定义的代码,类似于上面的@JsonSerialize

  1. public class CustomDateDeserialize extends JsonDeserializer<Date> {
  2. private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  3. @Override
  4. public Date deserialize(JsonParser jp, DeserializationContext ctxt)
  5. throws IOException, JsonProcessingException {
  6. Date date = null;
  7. try {
  8. date = sdf.parse(jp.getText());
  9. } catch (ParseException e) {
  10. e.printStackTrace();
  11. }
  12. return date;
  13. }
  14. }
  • 完整例子
  1. //表示序列化时忽略的属性
  2. @JsonIgnoreProperties(value = { "word" })
  3. public class Person {
  4. private String name;
  5. private int age;
  6. private boolean sex;
  7. private Date birthday;
  8. private String word;
  9. private double salary;
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public int getAge() {
  17. return age;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. public boolean isSex() {
  23. return sex;
  24. }
  25. public void setSex(boolean sex) {
  26. this.sex = sex;
  27. }
  28. public Date getBirthday() {
  29. return birthday;
  30. }
  31. // 反序列化一个固定格式的Date
  32. @JsonDeserialize(using = CustomDateDeserialize.class)
  33. public void setBirthday(Date birthday) {
  34. this.birthday = birthday;
  35. }
  36. public String getWord() {
  37. return word;
  38. }
  39. public void setWord(String word) {
  40. this.word = word;
  41. }
  42. // 序列化指定格式的double格式
  43. @JsonSerialize(using = CustomDoubleSerialize.class)
  44. public double getSalary() {
  45. return salary;
  46. }
  47. public void setSalary(double salary) {
  48. this.salary = salary;
  49. }
  50. public Person(String name, int age) {
  51. this.name = name;
  52. this.age = age;
  53. }
  54. public Person(String name, int age, boolean sex, Date birthday,
  55. String word, double salary) {
  56. super();
  57. this.name = name;
  58. this.age = age;
  59. this.sex = sex;
  60. this.birthday = birthday;
  61. this.word = word;
  62. this.salary = salary;
  63. }
  64. public Person() {
  65. }
  66. @Override
  67. public String toString() {
  68. return "Person [name=" + name + ", age=" + age + ", sex=" + sex
  69. + ", birthday=" + birthday + ", word=" + word + ", salary="
  70. + salary + "]";
  71. }
  72. }
    1. public class Demo {
    2. public static void main(String[] args) {
    3. writeJsonObject();
    4. // readJsonObject();
    5. }
    6. // 直接写入一个对象(所谓序列化)
    7. public static void writeJsonObject() {
    8. ObjectMapper mapper = new ObjectMapper();
    9. Person person = new Person("nomouse", 25, true, new Date(), "程序员",
    10. 2500.0);
    11. try {
    12. mapper.writeValue(new File("c:/person.json"), person);
    13. } catch (JsonGenerationException e) {
    14. e.printStackTrace();
    15. } catch (JsonMappingException e) {
    16. e.printStackTrace();
    17. } catch (IOException e) {
    18. e.printStackTrace();
    19. }
    20. }
    21. // 直接将一个json转化为对象(所谓反序列化)
    22. public static void readJsonObject() {
    23. ObjectMapper mapper = new ObjectMapper();
    24. try {
    25. Person person = mapper.readValue(new File("c:/person.json"),
    26. Person.class);
    27. System.out.println(person.toString());
    28. } catch (JsonParseException e) {
    29. e.printStackTrace();
    30. } catch (JsonMappingException e) {
    31. e.printStackTrace();
    32. } catch (IOException e) {
    33. e.printStackTrace();
    34. }
    35. }
    36. }
    37. 如果Entity中的延迟加载对象必须有值,可以用Hibernate.initialize把延迟加载的对象提前获取
    38. Hibernate.initialize( Entity.getXX() );