Jackson的基本用法


一、依賴

    jackson依賴3個包,由於jackson-databind依賴於jackson-annotations,jackson-core,所以實際引用jackson-databind即可以。

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.8.1</version>
</dependency>

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.8.1</version>
</dependency>

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-annotations</artifactId>
  <version>2.8.1</version>
</dependency>

 

二、常用注解

1、@JsonAnyGetter, @JsonAnySetter:用於將字符串中未映射到屬性的值放在一個map;

@Data
public class DatasetDynamic {
    private String album_id;
    private String album_title;
@J private Map<String , Object> otherProperties = new HashMap<String , Object>(); @JsonCreator public DatasetDynamic(@JsonProperty("album_id") String album_id, @JsonProperty("album_title") String album_title) { this.album_id = album_id; this.album_title = album_title; } public Object get(String name) { return otherProperties.get(name); }
@JsonAnyGetter public Map<String , Object> any() { return otherProperties; }
@JsonAnySetter public void set(String name, Object value) { otherProperties.put(name, value); } }
      {
      "album_id":"123",
      "album_title":"haha",
      "test1":"heihei",
      "test2":222
      }

  輸出:DatasetDynamic(album_id=123, album_title=haha, otherProperties={test2=222, test1=heihei}) 

 

2、@JsonIgnoreProperties和@JsonIgnore: 

用於標記屬性,在json與java之間相互轉化時,將忽略被此注解標記的屬性。@JsonIgnoreProperties是類級別注解,可以忽略多個屬性,@JsonIgnore用來標注單個屬性。

@JsonIgnoreProperties({ "album_title" })
public class DatasetFilter {
    @JsonIgnore
    private String album_id;
    private String album_title;
    private Map<String , Object> otherProperties = new HashMap<String , Object>();
    private String album_comments;
}

  

3、@JsonRawValue: 直接顯示屬性值,對字符串,即是去掉雙引號。

public class PersonRawValue {
    public long   personId = 0;
    //@JsonRawValue
    public String address  = "$#";
}
不加注解顯示:{"personId":0,"address":"$#"}
加注解顯示:{"personId":0,"address":$#}

4、@JsonPropertyOrder:指對象屬性序列化的順序,指定順序的先顯示,沒有指定的按照默認順序在后面,@JsonFormat:時間格式化

@JsonPropertyOrder({"id","time","name"})
public class User {
   private Long id;
   private String name;
   private BigDecimal age;
   @JsonFormat(pattern = "yyyy-MM-dd")
   private Date date;
   @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
   private Timestamp time;
   public User(Long id, String name, Date date) {
      this.id = id;
      this.name = name;
      this.date = date;
   }
}

輸出結果:

{
  "id" : 2,
  "time" : null,
  "name" : "theUser",
  "age" : null,
  "date" : "2018-07-23"
}

 

5、@JsonInclude:控制序列化時的顯示,將該標記放在屬性上,如果該屬性為NULL則不參與序列化 。如果放在類上邊,那對這個類的全部屬性起作用 

Include.Include.ALWAYS 默認 
Include.NON_DEFAULT
屬性為默認值不序列化 
Include.NON_EMPTY
屬性為空(“”或者為 NULL 都不序列化 
Include.NON_NULL
屬性為NULL 不序列化 

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class User {
   private Long id;
}

 

6、@JsonSerialize@JsonDeserialize: 自定義序列化

// 自定義反序列化
public class ItemDeserializer extends JsonDeserializer<Item> {
    @Override
    public Item deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
            throws IOException, JsonProcessingException {
        JsonNode jsonNode = jsonParser.readValueAsTree();
        int id = jsonNode.path("id").intValue();
        String itemName = jsonNode.get("itemName").asText();
        Long userId = jsonNode.get("owner").asLong();
        return new Item(id, itemName, new User(userId, ""));
    }
}
// 自定義序列化
public class ItemSerializer extends JsonSerializer<Item> {
    @Override public void serialize(Item item, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeNumberField("id", item.id);
        jsonGenerator.writeStringField("itemName", item.itemName);
        jsonGenerator.writeNumberField("owner", item.getOwner().getId());
        //jsonGenerator.writeObjectField("owner", item.owner);
        jsonGenerator.writeEndObject();
    }
}

 應用方法有2種:

(1)注解方式:

@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonSerialize(using = ItemSerializer.class)
@JsonDeserialize(using = ItemDeserializer.class)
public class Item {
    public int id;
    public String itemName;
    public User owner;
}

(2)代碼方式:

SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Item.class, new ItemSerializer());
simpleModule.addDeserializer(Item.class, new ItemDeserializer());
ObjectMapper mapper = JacksonUtil.getNewDefaultMapper();
mapper.registerModule(simpleModule);
//...

 

7、@JsonCreator :解決多態性問題,通過注解,可以在序列化時,保存具體的類型信息到json中,當json反序列到java對象時,就可以根據具體類型信息創建正確的java對象。

當str -> bean時會調用@JsonCreator注解的構造函數,如果沒有此注解,則默認調用無參構造函數

@Data
public class Lion extends Animal {
    private String name;
    @JsonCreator
    public Lion(@JsonProperty("name") String name) {
        this.name = name;
    }
}
public static void main(String[] args) throws IOException {
    Lion lion = new Lion("jack");
    log.info(JacksonUtil.toJson(lion));
    log.info(JacksonUtil.jsonToBean(JacksonUtil.toJson(lion), Lion.class));
}

 輸出:

  "@class" : "vo.Lion",
  "name" : "jack",
  "sound" : null,
  "type" : null,
  "endangered" : null
} 
 [2018-08-26 21:03:47] main  INFO test.annotation.Test1.main(Test1.java:26) Lion(name=jack) 

 修改類:

@Data
@NoArgsConstructor
public class Lion extends Animal {
    private String name;
    public Lion(String name) {
        this.name = name;
    }
}
// 輸出結果:
  "@class" : "vo.Lion",
  "name" : "jack",
  "sound" : null,
  "type" : null,
  "endangered" : null
} 
 [2018-08-26 21:08:46] main  INFO test.annotation.Test1.main(Test1.java:26) Lion(name=jack) 

 

8、@JsonTypeInfo、@JsonSubTypes:解決多態性問題,通過注解,可以在序列化時,保存具體的類型信息到json中,當json反序列到java對象時,就可以根據具體類型信息創建正確的java對象

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
@JsonSubTypes({ @Type(value = Lion.class, name = "lion"), @Type(value = Elephant.class, name = "elephant") })
@Data
public abstract class Animal {
    @JsonProperty("name")
    String name;
    @JsonProperty("sound")
    String sound;
    @JsonProperty("type")
    String type;
    @JsonProperty("endangered")
    Boolean endangered;
}

@Data
public class Zoo {
    public String name;
    public String city;
    public List<Animal> animals = new ArrayList<Animal>();

    @JsonCreator
    public Zoo(@JsonProperty("name") String name,@JsonProperty("city") String city) {
        this.name = name;
        this.city = city;
    }
    public List<Animal> addAnimal(Animal animal) {
        animals.add(animal);
        return animals;
    }
}

@Data
@NoArgsConstructor
public class Lion extends Animal {
    private String name;
    @JsonCreator
    public Lion(@JsonProperty("name") String name) {
        this.name = name;
    }
}

@Data
@NoArgsConstructor
public class Elephant extends Animal {
    @JsonProperty
    private String name;
    @JsonCreator
    public Elephant(@JsonProperty("name") String name) {
        this.name = name;
    }
}

    public static void main(String[] args) throws IOException {
        Zoo zoo = new Zoo("London zoo", "London");
        Lion lion = new Lion("Simba");
        Elephant elephant = new Elephant("Manny");
        zoo.addAnimal(lion).add(elephant);
        String jsonStr = JacksonUtil.toJson(zoo);
        log.info(jsonStr);
        log.info(JacksonUtil.jsonToBean(jsonStr, Zoo.class));
    }

 輸出:

[2018-08-26 21:18:24] main  INFO test.annotation.Test1.main(Test1.java:26) {
  "name" : "London zoo",
  "city" : "London",
  "animals" : [ {
    "@class" : "vo.Lion",
    "name" : "Simba",
    "sound" : null,
    "type" : null,
    "endangered" : null
  }, {
    "@class" : "vo.Elephant",
    "name" : "Manny",
    "sound" : null,
    "type" : null,
    "endangered" : null
  } ]
} 
 [2018-08-26 21:18:24] main  INFO test.annotation.Test1.main(Test1.java:27) Zoo(name=London zoo, city=London, animals=[Lion(name=Simba), Elephant(name=Manny)]) 

 這里面有個問題,Jackson是如何識別具體的實現類?有2個問題解答:(1)區分實現類的標識?(2)標識如何寫入?

注解:@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")  //使用類限定名區分,標識作為數據的史弟屬性定入

具體參數:

use:定義使用哪一種類型識別碼,它有下面幾個可選值:
1、JsonTypeInfo.Id.CLASS:使用完全限定類名做識別
2、JsonTypeInfo.Id.MINIMAL_CLASS:若基類和子類在同一包類,使用類名(忽略包名)作為識別碼
3、JsonTypeInfo.Id.NAME:一個合乎邏輯的指定名稱
4、JsonTypeInfo.Id.CUSTOM:自定義識別碼,
5、JsonTypeInfo.Id.NONE:不使用識別碼
include(可選):指定識別碼是如何被包含進去的,它有下面幾個可選值:
1、JsonTypeInfo.As.PROPERTY:作為數據的兄弟屬性
2、JsonTypeInfo.As.EXISTING_PROPERTY:作為POJO中已經存在的屬性
3、JsonTypeInfo.As.EXTERNAL_PROPERTY:作為擴展屬性
4、JsonTypeInfo.As.WRAPPER_OBJECT:作為一個包裝的對象
5、JsonTypeInfo.As.WRAPPER_ARRAY:作為一個包裝的數組

 

三、ObjectMapper常用配置:

    private static ObjectMapper mapper = new ObjectMapper();

    static {
        mapper.enable(SerializationFeature.INDENT_OUTPUT); //化化輸出
        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); //序列化空的POPJ
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); //不將date轉化成timestamp
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); //忽略未知屬性
        mapper.disable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); //不將空轉化為null
        mapper.disable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES); //允許沒有引號的字段名(非標准)
        mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }

 

四、Jackson模型:【待補充】

 

附1:封裝類

/**
 * 例1:String str = JacksonUtil.toJson(userList);
 * 例2:User u = JacksonUtil.jsonToBean(str, User.class);
 * 例3:List<User> userList = JacksonUtil.jsonTo(str, new TypeReference<List<User>>(){});
 * 例4:Map<String, User> map = JacksonUtil.jsonTo(str, new TypeReference<Map<String, User>(){});
 */

@Log4j2
public class JacksonUtil {
    private static ObjectMapper mapper = new ObjectMapper();

    static {
        mapper.enable(SerializationFeature.INDENT_OUTPUT); //化化輸出
        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); //序列化空的POPJ
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); //不將date轉化成timestamp
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); //忽略未知屬性
        mapper.disable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); //不將空轉化為null
        mapper.disable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES); //允許沒有引號的字段名(非標准)
        mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }

    public JacksonUtil() {
    }

    public static ObjectMapper getNewMapper() {
        return new ObjectMapper();
    }

    public static ObjectMapper getNewDefaultMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); //序列化空的POPJ
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); //不將date轉化成timestamp
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); //忽略未知屬性
        mapper.disable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); //不將空轉化為null
        mapper.disable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES); //允許沒有引號的字段名(非標准)
        mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        return mapper;
    }

    public static <T> String toJson(T t) {
        return toJson(t, null);
    }

    public static <T> T jsonTo(String json, TypeReference<T> typeReference) {
        return jsonTo(json, typeReference, null);
    }

    public static <T> T jsonToBean(String json, Class<T> clazz) {
        return jsonToBean(json, clazz, null);
    }

    public static <T> T fileToBean(File file, Class<T> clazz) {
        return fileToBean(file, clazz, null);
    }

    public static <T> String toJson(T t, ObjectMapper objectMapper) {
        if (Objects.isNull(t))
            return null;
        try {
            return objectMapper == null ? mapper.writeValueAsString(t) : objectMapper.writeValueAsString(t);
        } catch (JsonProcessingException e) {
            log.error("to json error:" + t, e);
            return null;
        }
    }

    public static <T> T jsonToBean(String json, Class<T> clazz, ObjectMapper objectMapper) {
        if (StringUtils.isBlank(json))
            return null;
        try {
            return objectMapper == null ? mapper.readValue(json, clazz) : objectMapper.readValue(json, clazz);
        } catch (IOException e) {
            log.error("json to bean error:" + json, e);
            return null;
        }
    }

    public static <T> T fileToBean(File file, Class<T> clazz, ObjectMapper objectMapper) {
        if (!file.exists())
            return null;
        try {
            return objectMapper == null ? mapper.readValue(file, clazz) : objectMapper.readValue(file, clazz);
        } catch (IOException e) {
            log.error("file to bean error:" + file.getName(), e);
            return null;
        }
    }

    public static <T> T jsonTo(String json, TypeReference<T> typeReference, ObjectMapper objectMapper) {
        if (StringUtils.isBlank(json))
            return null;
        try {
            return objectMapper == null ? mapper.readValue(json, typeReference) : objectMapper.readValue(json, typeReference);
        } catch (Exception e) {
            log.error("json to map error:" + json, e);
            return null;
        }
    }

    public static <T> T jsonTo(String json, Class<T> clazz, ObjectMapper objectMapper) {
        if (StringUtils.isBlank(json))
            return null;
        try {
            return mapper.readValue(json, new TypeReference<T>(){});
        } catch (Exception e) {
            log.error("json to map error:" + json, e);
            return null;
        }
    }
}

  

 

 

 









 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM