zoukankan      html  css  js  c++  java
  • Jackson ObjectMapper JSON序列化工具使用笔记,由浅入深

    Apache Dubbo 官方放弃了FastJson

    Jackson目前是世界上最好的Java JSON库。

    基本用法,ObjectNode, ArrayNode等 ValueNode

    生成一个 jsonobject结构
    ObjectNode protocol = new ObjectNode(JsonNodeFactory.instance);
    //或者 ObjectNode protocol = JsonNodeFactory.instance.objectNode();
    
    protocol.put("batchSize", 20480);
    protocol.putArray("columns").add("id").add("name");
    
    把数组、List作为一个带名称的 jsonarray 结构
    List<xxx> costs = ...
    ObjectNode x = JsonNodeFactory.instance.objectNode().putPOJO("costs", costs);
    
    字符串反序列化为List、数组
    //slankka提示1: 数据是List的
    objectMapper.readValue(str, new TypeReference<List<Item>>() {});
    
    序列化任意对象、数组
    objectMapper.writeValueAsString(object);
    

    JsonNode 操作

    修改JsonNode

    注意:需要强转ObjectNode

    没必要因为个别字段不一致就专门定义一个POJO,太繁琐。

    本身做Controller就是为了生成JSON,而JSON就是Javascript Object Notation

    例如service 字段转成 codec里面的value值,根据fromId 生成一个新newRef值。

    Map<String, String> codec ...
    Map<Long, String> laborRefNames ...
    JsonNode jsonNodes = new ObjectMapper().valueToTree(iterableVals);
    jsonNodes.forEach(x -> ((ObjectNode) x)
             .put("service", codec.get(x.get("service").asText()))
             .put("newRef", laborRefNames.get(x.get("fromId").asLong())));
    
    从JsonNode中获取JsonArray,再反序列化成对象
    //slankka提示2:从JsonNode中获取一个JsonArray (JsonNode类型)
    //slankka提示3:MetricsPack是一个ArrayList子类,与前文的TypeReference不同,这里是一个技巧。
    metrics = objectMapper.treeToValue(jsonNode.get("metrics"), MetricsPack.class);
    
    字符串反序列化为JsonNode,并不直接转换成对象

    做接口设计的时候,比较好用,不关心具体的数据类差异,只关心数值字段

    JsonNode jsonNode = objectMapper.readTree(str_input);
    
    interface DataExtractor {
      Object handle(JsonNode jsonNode);
    }
    
    DataExtractor instance;
    instance.handle(jsonNode);
    
    从JsonNode中获取数值
    //十分灵活,需要字符串就是字符串,需要转成int就是int。(前提是数据类型比较符合,Javascript本身就是灵活的)
    int instanceId = jsonNode.get("instanceId").asInt();
    String text = jsonNode.get("instanceId").asText();
    
    //Slankka提示4:一定要调用 asInt, asLong, asText,否则获取得到的是JsonNode, 他有toString,容易被误用。
    Timestamp timestamp = Timestamp.from(Instant.ofEpochMilli(jsonNode.get("createTime").asLong()));
    Optional.ofNullable(jsonNode.get("room")).map(JsonNode::asText).orElse(null)
    
    使用JsonPath语法获取数值

    使用JsonPath更为简洁,可以替代上述jsonNode.get()语法

     slankka.setTopicName(jsonNode.at("/additional/topicName").asText());
     slankka.setReplica((short) jsonNode.at("/additional/replica").asInt());
     slankka.setUserId(jsonNode.at("/additional/userId").asInt());
     slankka.setClusterId((short) jsonNode.at("/additional/clusterId").asInt());
     slankka.setPartitionNum(jsonNode.at("/additional/partitionNum").asInt());
    

    高级用法

    使用泛型 + ArrayList子类 + 某种设计模式(模板模式?)
    //抽象盒子
    public abstract class PrototypeBox<T extends AbstractApp> extends ArrayList<T> {
       String whatBoxCanDo() {
            for (AbstractApp app : this) {
                app.whatAppCanDo();
            }
       };
    }
    
    //抽象物体单元
    public abstract class AbstractApp {
        protect String platform;
        protect Integer platId;
    
        public abstract String whichIsDifferent();
    
        public ObjectNode mayBeYouWantToSerialize() {
             ObjectNode _dataNode = new ObjectNode(JsonNodeFactory.instance);
             _dataNode.put("Question", "我们哪里不一样?" +  whichIsDifferent() );
             return _dataNode;
        }
    
        void whatAppCanDo() {
            mayBeYouWantToSerialize();
        };
    }
    
    //派生物体A
    public class IosApp extends AbstractApp {
        public static class Pack extends PrototypeBox<IosApp> {
        }
    }
    
    //派生物体B
    public class AndroidApp extends AbstractApp {
        public static class Pack extends PrototypeBox<AndroidApp> {
        }
    }
    
    //场景1
    IosApp.Pack anApps = null;
    try {
        anApps = objectMapper.treeToValue(at, IosApp.Pack.class);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
    //场景2
    AndroidApp.Pack anApps = null;
    try {
        anApps = objectMapper.treeToValue(at, AndroidApp.Pack.class);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
    
    //Slankka提示5:处理方式,由上到下,由外及内。
    anApps.whatBoxCanDo();
    

    这个例子最复杂,总而言之,其实就是两种对象数组(List),他们不一样,但是大部分属性,方法是共同的。

    好处就是可以一并处理,各自再处理不同的细节。

    这样设计,是服从高内聚,低耦合的原则的。

    附录:

    StringBoot中jackson的配置

    可大写也可小写,可搜索spring.jackson.serialization查看SpringBoot Jar包源码支持的其他类型

    例如

        {
          "name": "spring.jackson.serialization",
          "type": "java.util.Map<com.fasterxml.jackson.databind.SerializationFeature,java.lang.Boolean>",
          "description": "Jackson on/off features that affect the way Java objects are serialized.",
          "sourceType": "org.springframework.boot.autoconfigure.jackson.JacksonProperties"
        }
    

    例:

    # 将日期类型序列化为TIMESTAMP时间戳字符串
    spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=true
    # 将BIGDECIMAL序列化为 bigDecimal.toPlainString(), 防止生成科学计数法
    spring.jackson.generator.WRITE_BIGDECIMAL_AS_PLAIN=true
    

    ※Spring把这个选项设置为false

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(ObjectMapper.class)
    public class JacksonAutoConfiguration {
    	private static final Map<?, Boolean> FEATURE_DEFAULTS;
    
    	static {
    		Map<Object, Boolean> featureDefaults = new HashMap<>();
    		featureDefaults.put(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    		featureDefaults.put(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
    		FEATURE_DEFAULTS = Collections.unmodifiableMap(featureDefaults);
    	}
    }
    
  • 相关阅读:
    atitit.TokenService v3 qb1 token服务模块的设计 新特性.docx
    Atitit attilax在自然语言处理领域的成果
    Atitit 图像清晰度 模糊度 检测 识别 评价算法 原理
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结
    atitit。企业的价值观 员工第一 vs 客户第一.docx
    Atitit 实现java的linq 以及与stream api的比较
    Atitit dsl exer v3 qb3 新特性
    Atititi tesseract使用总结
    Atitit 修改密码的功能流程设计 attilax总结
    atitit.TokenService v3 qb1  token服务模块的设计 新特性.docx
  • 原文地址:https://www.cnblogs.com/slankka/p/15478064.html
Copyright © 2011-2022 走看看