【问题标题】:Jackson Serialization issue with CommonsMultipartFileCommonsMultipartFile 的 Jackson 序列化问题
【发布时间】:2011-07-22 19:08:55
【问题描述】:

我有一个带有 CommonsMultipartFile 类型字段的 bean,如下所示:

public class Placement implements Serializable {

private static final long serialVersionUID = 1L;

private long placementId;
private String type;
private String placement;
private transient CommonsMultipartFile fileData;

我已将 CommonsMultipartFile 字段标记为瞬态并尝试使用 jackson 库序列化为 json。但出现以下错误:

org.codehaus.jackson.map.JsonMappingException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: nextag.travel.dashboard.model.Placement["fileData"]->org.springframework.web.multipart.commons.CommonsMultipartFile["inputStream"])

任何帮助/建议将不胜感激。

【问题讨论】:

  • 如何公开私有字段?用吸气剂?使用修改后的 VisibilityChecker?你用什么代码来序列化?

标签: java json serialization jackson


【解决方案1】:

不清楚 Jackson 是如何被使用的,因为原始问题中没有提供代码或描述。

默认情况下,Jackson 在序列化过程中会跳过所有瞬态字段。

import java.io.Serializable;

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.map.ObjectMapper;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setVisibilityChecker(mapper.getVisibilityChecker().withFieldVisibility(Visibility.ANY));
    System.out.println(mapper.writeValueAsString(new Placement()));
    // output:  {"placementId":42,"type":"OK","placement":"left"}
    // transient fields are skipped by default
  }
}

class Placement implements Serializable
{
  private static final long serialVersionUID = 1L;

  private long placementId = 42;
  private String type = "OK";
  private String placement = "left";
  private transient CommonsMultipartFile fileData = new CommonsMultipartFile();
}

class CommonsMultipartFile
{
  private String name = "Fred";
}

但是,如果瞬态字段有一个 getter,那么默认情况下,Jackson 在序列化期间包含它。

import java.io.Serializable;

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.map.ObjectMapper;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setVisibilityChecker(mapper.getVisibilityChecker().withFieldVisibility(Visibility.ANY));
    System.out.println(mapper.writeValueAsString(new Placement()));
    // output: {"placementId":42,"type":"OK","placement":"left","fileData":{"name":"Fred"}}
    // transient fields with getters are not skipped by default
  }
}

class Placement implements Serializable
{
  private static final long serialVersionUID = 1L;

  private long placementId = 42;
  private String type = "OK";
  private String placement = "left";
  private transient CommonsMultipartFile fileData = new CommonsMultipartFile();

  public CommonsMultipartFile getFileData() {return fileData;}
}

class CommonsMultipartFile
{
  private String name = "Fred";
}

跳过 getter 的一个配置选项是只应用 @JsonIgnore 注释。

import java.io.Serializable;

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.ObjectMapper;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setVisibilityChecker(mapper.getVisibilityChecker().withFieldVisibility(Visibility.ANY));
    System.out.println(mapper.writeValueAsString(new Placement()));
    // output: {"placementId":42,"type":"OK","placement":"left"}
    // getters marked with @JsonIgnore are ignored
  }
}

class Placement implements Serializable
{
  private static final long serialVersionUID = 1L;

  private long placementId = 42;
  private String type = "OK";
  private String placement = "left";
  private transient CommonsMultipartFile fileData = new CommonsMultipartFile();

  @JsonIgnore
  public CommonsMultipartFile getFileData() {return fileData;}
}

class CommonsMultipartFile
{
  private String name = "Fred";
}

如果无法或不希望编辑原始类定义以添加@JsonIgnore 注释,则可以使用Mix-In

import java.io.Serializable;

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.ObjectMapper;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setVisibilityChecker(mapper.getVisibilityChecker().withFieldVisibility(Visibility.ANY));
    mapper.getSerializationConfig().addMixInAnnotations(Placement.class, SkipFileDataMixIn.class);
    System.out.println(mapper.writeValueAsString(new Placement()));
    // output: {"placementId":42,"type":"OK","placement":"left"}
    // getters marked with @JsonIgnore are ignored
  }
}

abstract class SkipFileDataMixIn
{
  @JsonIgnore
  public abstract CommonsMultipartFile getFileData();
}

class Placement implements Serializable
{
  private static final long serialVersionUID = 1L;

  private long placementId = 42;
  private String type = "OK";
  private String placement = "left";
  private transient CommonsMultipartFile fileData = new CommonsMultipartFile();

  public CommonsMultipartFile getFileData() {return fileData;}
}

class CommonsMultipartFile
{
  private String name = "Fred";
}

另一种方法是用@JsonIgnoreType标记要跳过的类型。

import java.io.Serializable;

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonIgnoreType;
import org.codehaus.jackson.map.ObjectMapper;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setVisibilityChecker(mapper.getVisibilityChecker().withFieldVisibility(Visibility.ANY));
    System.out.println(mapper.writeValueAsString(new Placement()));
    // output: {"placementId":42,"type":"OK","placement":"left"}
    // Types marked with @JsonIgnoreType are ignored during serialization.
  }
}

class Placement implements Serializable
{
  private static final long serialVersionUID = 1L;

  private long placementId = 42;
  private String type = "OK";
  private String placement = "left";
  private transient CommonsMultipartFile fileData = new CommonsMultipartFile();

  public CommonsMultipartFile getFileData() {return fileData;}
}

@JsonIgnoreType
class CommonsMultipartFile
{
  private String name = "Fred";
}

【讨论】:

  • 为我节省了很多时间..!!谢谢
【解决方案2】:

如果您不想序列化多部分文件,请在字段中添加注释@JsonIgnore

@JsonIgnore
private CommonsMultipartFile fileData;

您可以阅读更多 abot jackson 注释here

【讨论】:

    猜你喜欢
    • 2021-12-31
    • 2018-10-26
    • 2016-10-06
    • 2016-12-24
    • 2018-10-06
    • 2017-06-25
    • 2020-02-05
    • 2020-09-25
    • 1970-01-01
    相关资源
    最近更新 更多