• fastjson的字段


    fastjson是Alibaba开源的一套JSON处理工具类,用起来很方便,在项目中经常会使用到,强大的注解可以将JSON和Java对象玩出花来,在使用fastjson之前,需要先搞清楚几个概念:
    (1)序列化与反序列化
    往简单了说,序列化指的就是将Java对象转化为字符串/文件/流,总之就是将Java对象设置为可以看到的形式,而反序列化,就是将文件/流/字符串解析为Java对象。工作中比较常用的序列化和反序列化包括如下几个场景:

    • 第三方丢给你一个*.json文件,然后要保存到数据库中
    • 从数据库读取大量数据,传输给前端或者第三方人员
    • 读取Excel文件,然后处理Excel(修改值/保存到数据库)
      以上这些场景,先不管数据量多少的问题,单单是这么多单位的命名风格就各地迥异,而且可能是其他语言如Python、C++生成的,没有一个统一的规范,python是下划线分隔,Excel是中文,这还仅仅是读取。对于发送给第三方使用,对方也会要求使用固定的字段名称,我们能决定的,只是Java实体类的字段名(驼峰命名法),但是这又跟数据的处理没有关系。

    (2)fastjson的注解——@JsonField
    注解@JsonField可以做到读取json文件的是否适配字段A_b(反序列化),提供json的是否给字段aB(序列化),这一切都是靠的注解@JsonField,该注解具有如下属性:

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
    public @interface JSONField {
      	int ordinal() default 0; //是根据fieldName的字母序进行序列的,你可以通过ordinal指定字段的顺序
    
            String name() default ""; //序列化和反序列化时候的别名
    
            String format() default ""; //用于字符串格式的日期转换
    
            boolean serialize() default true; // 是否参与序列化
    
            boolean deserialize() default true; //是否参与反序列化
    
            SerializerFeature[] serialzeFeatures() default {}; //序列化选项 SerializerFeature.WriteNullNumberAsZero 如空Number填充0
    
            Feature[] parseFeatures() default {}; //反序列化选项
    
            String label() default ""; //标签,
    
            boolean jsonDirect() default false; //当你有⼀个字段是json字符串的数据,你希望直接输出,⽽不是经过转义之后再输出。
    
            Class<?> serializeUsing() default Void.class; // 属性的序列化类,可定制。可有现存的,比如本来是Long,序列化的时候转为String:serializeUsing= ToStringSerializer.class
    
        	Class<?> deserializeUsing() default Void.class; // 属性的反序列化类,可定制。
    
        	String[] alternateNames() default {}; //参与反序列化时候的别名
    
            boolean unwrapped() default false; // 对象映射到父对象上。不进行子对象映射。简单而言,就是属性为对象的时候,属性对象里面的属性直接输出当做父对象的属性输出
    
            String defaultValue() default ""; //设置默认值
    }
    

    很明显,从注释中可以看出,@JsonField的属性也是分为序列化和反序列化的,面对不同的场景,要选用不同的属性,下面结合具体的实例来讲解fastjson的使用

    • 项目类型:Springboot,且默认的JSON转换器设置为fastjson
    • 设置默认的JSON Convertor
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import com.alibaba.fastjson.support.config.FastJsonConfig;
    import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
    import java.nio.charset.Charset;
    import java.util.ArrayList;
    import java.util.List;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    @EnableWebMvc
    public class WebConfig implements WebMvcConfigurer {
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
            FastJsonConfig config = new FastJsonConfig();
            config.setCharset(Charset.forName("UTF-8"));
            config.setDateFormat("yyyyMMdd HH:mm:ssS");
            //设置允许返回为null的属性
            config.setSerializerFeatures(SerializerFeature.WriteMapNullValue);
            fastJsonConverter.setFastJsonConfig(config);
            List<MediaType> list = new ArrayList<>();
            list.add(MediaType.APPLICATION_JSON_UTF8);
            fastJsonConverter.setSupportedMediaTypes(list);
            converters.add(fastJsonConverter);
        }
    }
    
    • 实体类
    @NoArgsConstructor
    @Data
    public class ProfileRecord {
    
      @JSONField(name = "api_id", alternateNames = "api_id")
      private String apiId;
      @JSONField(name = "code", deserialize = false)
      private Integer code;
      @JSONField(name = "data", serialize = false, deserialize = false)
      private DataDTO data;
      @JSONField(name = "msg")
      private String msg;
      @JSONField(name = "requestId")
      private String requestId;
      @JSONField(name = "version")
      private String version;
      }
    }
    
    • json文件
    {
      "api_idd": "10086",
      "code": 0,
       "msg": "成功",
      "requestId": "a8fa3ebb959793ed",
      "version": "2022-03-10"
    }
    

    为了方便,直接在Controller层中读取json文件

    @RestController
    @RequestMapping("/profile")
    public class ProfileRecordController {
      @SneakyThrows
      @GetMapping("/list")
      public ProfileRecord get() {
        InputStream inputStream = FileReadUtil.getInstance()
            .getInputStream("static/profileRecord.json");
        String string = FileReadUtil.getInstance().getString(inputStream);
        ProfileRecord profileRecord = JSONObject.parseObject(string, ProfileRecord.class);
        inputStream.close();
        return profileRecord;
      }
    }
    

    关于上面的FileReadUtil工具类,是一个专门读取文件的类,可以参考本人的另一篇文章,
    (如果读者有更好的读取JSON文件的方式,可以在评论区交流)
    然后返回字符串,这里读取的是json文件,所以返回的字符串也就是json字符串,这种方式称之为反序列化,所以在java类中需要在字段上配置alternateNames 属性

    @JSONField(name = "api_id", alternateNames = "api_id")
    private String apiId;
    

    那为什么这里有name属性呢,是因为name是用于序列化后返回给前端的字段名称
    有几点需要注意:

    1. 如果不写 @JSONField注解,则默认使用Java类的字段名称来匹配JSON文件的字段名称,如apiId字段必须匹配的是json文件的apiId,但是这里提供的是api_id,所以必须加上反序列化属性alternateNames = "api_id"
    2. 如果不写 @JSONField注解,默认返回给前端的JSON,即序列化之后的JSON,字段名也是Java类的属性名,即apiId,要想迎合甲方或者客户,就必须使用 name属性;
    3. 如果只有属性name, 而没有属性alternateNames,则正反序列化都是使用name的值,即匹配JSON文件的字段和返回给前端的字段,都是api_id

    (3)不需要解析和返回的字段
    有时候为了提高处理速度,或者不希望某些字段值对外公开,则需要进行过滤,读取JSON文件时(反序列化),如果不希望读取某个字段,则可以在该字段的@JSONField注解上加上属性deserialize = false,这样Java对象中该属性的值就是null,而如果不希望对外暴露某个字段的值,则添加属性serialize = false,这样前端人员或者Spider就不会拿到这些属性的值了。
    PS:其实关于隐藏字段的方式Springboot默认的JSON处理器jackson中是有对应的注解和属性的,即@JsonIgnore,但是转换器HttpMessageConverter只能选择一个,这里我们选择的是FastJsonHttpMessageConverter,所以jackson的使用方式不在讨论之列。

  • 相关阅读:
    erlang中变量作用域
    erlang数字转字符串
    gen_server笔记
    Using Eredis, Redis With Erlang
    erlang lists模块函数使用大全
    erlang抽象码与basho的protobuf
    Erlang Module and Function
    Erlang中频繁发送远程消息要注意的问题
    Erlang中的record与宏
    数据结构之数羊问题
  • 原文地址:https://www.cnblogs.com/dabenhou/p/15990769.html
Copyright © 2020-2023  润新知