欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

fasterxml解析json篇

程序员文章站 2022-03-10 12:13:18
...

1

github demo:https://github.com/FasterXML/jackson-databind

2

maven依赖:

		 <dependency.version.jackson>2.8.8</dependency.version.jackson>

        <!-- Jackson依赖库 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${dependency.version.jackson}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${dependency.version.jackson}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${dependency.version.jackson}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
            <version>${dependency.version.jackson}</version>
        </dependency>

		<!-- 以下是bean复制工具 -->
		<dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.7.0</version>
        </dependency>
    

JacksonUtil.java

public class JacksonUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(JacksonUtil.class);

    private static final ObjectMapper objectMapper = new ObjectMapper();

    static {
        /*
         * 默认false:不解析含有注释符(即:true时解析含有注释的json字符串)<br>
         * 该特性,决定了解析器是否可以解析含有Java/C++注释样式(如:/*或//的注释符)<br>
         * 注意:标准的json字符串格式没有含有注释符(非标准),然而则经常使用<br>
         */
        objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
        /*
         * 默认false:不解析含有结束语的字符<br> 该特性,决定了解析器是否可以解析该字符(结束语字段符,一般在js中出现)<br>
         * 注意:标准的json字符串格式没有含有注释符(非标准),然而则经常使用<br>
         */
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        /*
         * 默认false:不解析含有单引号的字符串或字符<br>
         * 该特性,决定了解析器是否可以解析单引号的字符串或字符(如:单引号的字符串,单引号'\'')<br>
         * 注意:可作为其他可接受的标记,但不是JSON的规范<br>
         */
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        /*
         * 允许:默认false_不解析含有结束语控制字符<br>
         * 该特性,决定了解析器是否可以解析结束语控制字符(如:ASCII<32,如包含tab或换行符)<br>
         * 注意:设置false(默认)时,若解析则抛出异常;若true时,则用引号即可转义<br>
         */
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
        /*
         * 可解析反斜杠引用的所有字符,默认:false,不可解析
         */
        objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
        /**
         * 按字母顺序排序
         */
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
        /**
         * 忽略null
         */
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        objectMapper.setLocale(Locale.CHINA);
        objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false);
        
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false);

        // 将locadatetime 按照yyyy-MM-dd HH:mm:ss打印
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class,
                new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        objectMapper.registerModule(javaTimeModule);
    }

    /**
     * 对象转JSON
     *
     * @param object
     *            对象
     * @return String
     */
    public static String toJSONString(Object object) {
        String json = "";
        if (null == object) {
            return json;
        }
        try {
            json = objectMapper.writeValueAsString(object);
        } catch (IOException e) {
            LOGGER.error("Java 转 JSON 出错!", e);
            e.printStackTrace();
        }
        return json;
    }

    /**
     * 对象转JSON
     *
     * @param object
     *            对象
     * @param pattern
     *            字符串时间格式规则, 如 "yyyy-MM-dd HH:mm:ss"
     * @return String
     */
    public static String toJSONString(Object object, String pattern) {
        String json = "";
        if (null == object) {
            return json;
        }
        ObjectMapper mapper = objectMapper;
        try {
            DateFormat dateFormat = new SimpleDateFormat(pattern);
            mapper = mapper.setDateFormat(dateFormat);
            json = mapper.writeValueAsString(object);
        } catch (IOException e) {
            LOGGER.error("Java 转 JSON 出错!", e);
            e.printStackTrace();
        }
        return json;
    }

    /**
     * 将json字符串转换为java对象
     * 
     * @param json
     *            json字符串
     * @param typeReference
     *            复杂的java对象类型
     * @param <T>
     * @return
     */
    public static <T> T jsonToBean(String json, TypeReference typeReference) {
        try {
            return objectMapper.readValue(json, typeReference);
        } catch (Exception e) {
            LOGGER.error("jsonToBeanByTypeReference", e);
            e.printStackTrace();
        }
        return null;
    }

    /**
     * map 转JavaBean
     */
    public static <T> T map2bean(Map map, Class<T> clazz) {
        return objectMapper.convertValue(map, clazz);
    }
}

3 使用

1 映射entity

jsonToBean:

        List<JsonEntity> jsonEntityList = JacksonUtil.jsonToBean(message, new TypeReference<List<JsonEntity>>(){});
        

注意:entity不要定义成List。

2 直接读取

示例:

    public List<UserEventEntity> parse(String message) throws IOException{
        List<UserEventEntity> list = new ArrayList<>();
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(message);
        boolean active = jsonNode.get("Hadoop:service=NameNode,name=FSNamesystem").get("tag.HAState").textValue().equals("active");
        if(active){
            JsonNode innerNode = objectMapper.readTree(jsonNode.get("Hadoop:service=NameNode,name=FSNamesystemState").get("TopUserOpCounts").textValue());
            /**
             * topUserOpCounts 结构:
             * topUserOpCounts (string) : v (string) 其中String类型的v如下: (即innerNode)
             *
             *     {
             * 	    "timestamp": "2019-06-25T16:57:11+0800",
             * 	    "windows": [{
             * 		    "windowLenMs": 60000,
             * 		    "ops": [{
             * 			    "opType": "listStatus",
             * 			    "topUsers": [{
             * 					"user": "voyager",
             * 					"count": 82
             *                },
             *                {
             * 					"user": "wave_bi",
             * 					"count": 1
             *                }
             * 			    ],
             * 			    "totalCount": 83
             * 		    }]
             * 	     }]
             *      }
             *
             *     其中,需要set给entity的字段如下:
             *     timestamp : 上述的timestamp字段如xxx
             *     opType    : 上述的opType
             *     opTotalSum: 将totalCount放在每个topUsers中的值,每个user都含有一样的总值
             *     userName  : 上述user
             *     opSum     : 上述count
             *     windowLenMs:放到每个user中
             *
             *     另外,额外设置一个entity,其 user = all ,并设置其 opTotalSum
             */
            String timestamp = innerNode.get("timestamp").textValue();
            innerNode.get("windows").forEach(e-> {
                long windowLenMs = e.get("windowLenMs").longValue();
                e.get("ops").forEach(f->{
                    String opType = f.get("opType").textValue();
                    long totalCount = f.get("totalCount").longValue();
                    UserEventEntity a = new UserEventEntity();
                    a.setUserName("all"); //这是一个统计用户
                    a.setOpTotalSum(totalCount);
                    a.setOpSum(totalCount);
                    a.setOpType(opType);
                    a.setWindowLenMs(windowLenMs);
                    a.setTimestamp(timestamp);
                    list.add(a);
                    f.get("topUsers").forEach(g->{
                        String user = g.get("user").textValue();
                        long count = g.get("count").longValue();
                        UserEventEntity u = new UserEventEntity();
                        u.setTimestamp(timestamp);
                        u.setWindowLenMs(windowLenMs);
                        u.setOpType(opType);
                        u.setUserName(user);
                        u.setOpSum(count);
                        u.setOpTotalSum(totalCount);
                        list.add(u);
                    });
                });
            });
        }
        return list;
    }