springboot-Jackson

在json的解析等处理方面,我更喜欢用阿里巴巴的Fastjson。Jackson也有许多实用的功能。今天整理几个比较常用的jackson实用功能:

示例代码

@RequestMapping("getuser")
@ResponseBody
public User getUser() {
    User user = new User();
    user.setUserName("mrbird");
    user.setBirthday(new Date());
    return user;
}
public class User implements Serializable {
    private static final long serialVersionUID = 6222176558369919436L;
    
    private String userName;
    private int age;
    private String password;
    private Date birthday;
    ...
}

# 项目中统一返回时间格式化

访问getuser页面输出:

{"userName":"mrbird","age":0,"password":null,"birthday":1522634892365}

可看到时间默认以时间戳的形式输出,如果想要改变这个默认行为,我们可以自定义一个ObjectMapper来替代:

import java.text.SimpleDateFormat;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.fasterxml.jackson.databind.ObjectMapper;

@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper getObjectMapper(){
        ObjectMapper mapper = new ObjectMapper();
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        return mapper;
    }
}

上面配置获取了ObjectMapper对象,并且设置了时间格式。再次访问getuser,页面输出:

{"userName":"mrbird","age":0,"password":null,"birthday":"2018-04-02 10:14:24"}

# Jackson注解

  • @JsonProperty
    作用在属性上,用来为JSON Key指定一个别名。
@JsonProperty("bth")
private Date birthday;

再次访问getuser页面输出:

{"userName":"mrbird","age":0,"password":null,"bth":"2018-04-02 10:38:37"}
  • @Jsonlgnore
    作用在属性上,用来忽略此属性。
@JsonIgnore
private String password;

再次访问getuser页面输出:

{"userName":"mrbird","age":0,"bth":"2018-04-02 10:40:45"}

password属性已被忽略。

  • @JsonIgnoreProperties
    忽略一组属性,作用于类上,比如JsonIgnoreProperties({ “password”, “age” })。
@JsonIgnoreProperties({ "password", "age" })
public class User implements Serializable {
    ...
}

再次访问getuser页面输出:

{"userName":"mrbird","bth":"2018-04-02 10:45:34"}
  • @JsonFormat
    用于日期格式化
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date birthday;
  • @JsonNaming
    用于指定一个命名策略,作用于类或者属性上。Jackson自带了多种命名策略,你可以实现自己的命名策略,比如输出的key 由Java命名方式转为下面线命名方法 —— userName转化为user-name。
@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
public class User implements Serializable {
    ...
}

再次访问getuser页面输出:

{"user_name":"mrbird","bth":"2018-04-02 10:52:12"}
  • @JsonSerialize
    指定一个实现类来自定义序列化。类必须实现JsonSerializer接口,代码如下:
import java.io.IOException;

import com.example.pojo.User;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

public class UserSerializer extends JsonSerializer<User> {

    @Override
    public void serialize(User user, JsonGenerator generator, SerializerProvider provider)
            throws IOException, JsonProcessingException {
        generator.writeStartObject();
        generator.writeStringField("user-name", user.getUserName());
        generator.writeEndObject();
    }
}

上面的代码中我们仅仅序列化userName属性,且输出的key是user-name。 使用注解@JsonSerialize来指定User对象的序列化方式:

@JsonSerialize(using = UserSerializer.class)
public class User implements Serializable {
    ...
}

再次访问getuser页面输出:

{"user-name":"mrbird"}
  • @JsonDeserialize
import java.io.IOException;

import com.example.pojo.User;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;

public class UserDeserializer extends JsonDeserializer<User> {

    @Override
    public User deserialize(JsonParser parser, DeserializationContext context)
            throws IOException, JsonProcessingException {
        JsonNode node = parser.getCodec().readTree(parser);
        String userName = node.get("user-name").asText();
        User user = new User();
        user.setUserName(userName);
        return user;
    }
}

使用注解@JsonDeserialize来指定User对象的序列化方式:

@JsonDeserialize (using = UserDeserializer.class)
public class User implements Serializable {
    ...
}

测试:

@Autowired
ObjectMapper mapper;

@RequestMapping("readjsonasobject")
@ResponseBody
public String readJsonAsObject() {
    try {
        String json = "{\"user-name\":\"mrbird\"}";
        User user = mapper.readValue(json, User.class);
        String name = user.getUserName();
        return name;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

访问readjsonasobject,页面输出:

mrbird
  • @JsonView
    作用在类或者属性上,用来定义一个序列化组。 比如对于User对象,某些情况下只返回userName属性就行,而某些情况下需要返回全部属性。 因此User对象可以定义成如下:
public class User implements Serializable {
    private static final long serialVersionUID = 6222176558369919436L;
    
    public interface UserNameView {};
    public interface AllUserFieldView extends UserNameView {};
    
    @JsonView(UserNameView.class)
    private String userName;
    
    @JsonView(AllUserFieldView.class)
    private int age;
    
    @JsonView(AllUserFieldView.class)
    private String password;
    
    @JsonView(AllUserFieldView.class)
    private Date birthday;
    ...	
}

User定义了两个接口类,一个为userNameView,另外一个为AllUserFieldView继承了userNameView接口。这两个接口代表了两个序列化组的名称。属性userName使用了@JsonView(UserNameView.class),而剩下属性使用了@JsonView(AllUserFieldView.class)。

Spring中Controller方法允许使用@JsonView指定一个组名,被序列化的对象只有在这个组的属性才会被序列化,代码如下:

@JsonView(User.UserNameView.class)
@RequestMapping("getuser")
@ResponseBody
public User getUser() {
    User user = new User();
    user.setUserName("mrbird");
    user.setAge(26);
    user.setPassword("123456");
    user.setBirthday(new Date());
    return user;
}

访问getuser页面输出:

{"userName":"mrbird"}

如果将@JsonView(User.UserNameView.class)替换为@JsonView(User.AllUserFieldView.class),输出:

{"userName":"mrbird","age":26,"password":"123456","birthday":"2018-04-02 11:24:00"}

因为接口AllUserFieldView继承了接口UserNameView所以userName也会被输出。

本文转载于MrBird

发布了20 篇原创文章 · 获赞 5 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_41762098/article/details/86525588