解析 json 大字段

需求:项目有个表(数据被其他服务实时更新)要解析里面一个字段,字段里面存储的 json 格式的字符串。

难点:研究发现,json 字符串内部,结构单一,但 json 内部包含数据量达到50多万,普通的json 解析方式肯定不是,会内存溢出的,只有用相应库中的流方式。

实现:这里不赘述其他实现,只把最核心的解析表中一行数据中那个存储 json 字段的解析过程的代码记录来下。

pom.xml


        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>

解析代码:

package test;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONReader;
import lombok.Data;

import java.io.CharArrayReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Test<O extends Keyable<String>> {
    /**
     * @param jsonStr
     * @param clazz
     * @return
     * @apiNote 将 jsonStr 转换为 Entity 的方法。显然解析出来的数据可能包含多条
     * @rule 既然是多条,也可能包含重复记录,默认不去重;
     * 如果需要去重请重写 内部的 filterRedundenceInJson 方法
     */
    private List<O> transfer2DTO(String jsonStr, Class<O> clazz) {

        //json string -> dto
        JSONObject root = null;
        try{
            root = JSON.parseObject(jsonStr);
        }catch (OutOfMemoryError e){
            System.err.println("内存溢出");
            //采用流式 API
            return this.transfer2DTOByStreamAPI(jsonStr,clazz);

        }


        if (root==null||!root.containsKey("tableModels")) {
            return null;
        }

        JSONArray arr = root.getJSONArray("tableModels");
        List<O> olist = arr.stream().map(e -> {
            JSONObject e1 = ((JSONObject) e);
            return e1.toJavaObject(clazz);
        }).collect(Collectors.toList());


        //去重
        return this.filterRedundenceInJson(olist);

    }

    /**
     * @param olist
     * @return
     * @apiNote 在相同 json 记录下的多余元素
     * @rule 既然是多条,也可能包含重复记录,默认按照 O 的 pkVal() 去重;
     * 如果需要去重请重写 内部的 filterRedundenceInJson 方法
     */
    protected List<O> filterRedundenceInJson(List<O> olist) {

        Map<String, O> map = new HashMap<>();
        olist.forEach(o -> {

            /**
             * 当前的去重逻辑是:保留第一条记录
             */
            if (!map.containsKey(o.getKey())) {
                map.put(o.getKey(), o);
            }

        });

        List<O> r = map.values().stream().collect(Collectors.toList());

        return r;
    }
    private List<O> transfer2DTOByStreamAPI(String jsonStr, Class<O> clazz) {

        List<O> olist = new ArrayList<>();
        JSONReader jsonReader = new JSONReader(new CharArrayReader(jsonStr.toCharArray()));
        jsonReader.startObject();
        Object key = jsonReader.readObject();
        /**
         * key 对应 的 value,
         * 由于我们需要进一步解析 value 内部细节,故不能直接简单获取其内容
         */
//        Object value = jsonReader.readObject();
        //进一步识别其为数组
        jsonReader.startArray();

        //遍历数组里面的内容
        while (jsonReader.hasNext()){
            //按整个对象进行读取
            O o = jsonReader.readObject(clazz);
            olist.add(o);
        }

        jsonReader.endArray();
        jsonReader.endObject();
        jsonReader.close();

        return  olist;

    }
    public static void main(String[] args) {
        String jsonStr = "{\"tableModels\":[{\"id\":\"1\",\"code\":\"111\",\"name\":\"jiangxu\"},{\"id\":\"1\",\"code\":\"111\",\"name\":\"jiangxu\"}]}";

        List<KeyValue> olist = new Test().transfer2DTO(jsonStr,KeyValue.class);
        olist.forEach(e->System.out.println(e));
    }

    @Data
    public static class  KeyValue implements Keyable<String> {
        private String id;
        private String code;
        private String name;

        @Override
        public String getKey() {
            return this.getId();
        }

    }




}

package test;

import lombok.Data;

@Data
public class  KeyValue implements Keyable<String> {
    private String id;
    private String code;
    private String name;

    @Override
    public String getKey() {
        return this.getId();
    }
}

package test;

public  interface Keyable<K extends Comparable<K>>{
    K getKey();
}

说明:这里的 json 数据形如:

{"tableModels":[{"id":"1","code":"j1","name":"jiang"},{...},{...},{...},....50w条]

<think>好的,我现在需要解决的问题是如何将包含前端样式的JSON字符串通过转义字符输出到控制台。首先,我得理解用户的具体需求。用户可能是在开发过程中遇到了需要将带有样式的文本(比如HTML或CSS)嵌入到JSON中,然后在JavaScript中解析并输出到控制台,同时保持样式有效的情况。这种情况常见于日志输出、调试信息美化等场景。 首先,JSON字符串中如果包含特殊字符,比如双引号、换行符或者反斜杠,需要使用转义字符来处理。例如,双引号在JSON中需要用反斜杠转义,写成\",而换行符则是\n。但问题在于,当这些字符串被解析后,直接输出到控制台时,可能需要保留某些样式,比如颜色、字体等,这时候可能需要使用控制台支持的样式语法,比如CSS样式或者ANSI转义码。 接下来,我需要考虑前端常用的控制台样式方法。在浏览器环境中,console.log支持使用%c占位符来应用CSS样式。例如: console.log('%c这是红色文本', 'color: red;'); 如果要将这样的样式嵌入到JSON字符串中,就需要在JSON中正确转义这些样式内容。比如,一个包含样式占位符和样式的JSON对象可能如下: { "message": "%cHello World", "styles": "color: red; font-size: 20px;" } 然后通过解析这个JSON,将message和styles传递给console.log。但用户提到的是通过转义字符将前端样式输出到控制台,可能是指直接在JSON字符串中包含转义后的样式信息,然后在解析后能够正确应用。 可能的步骤是: 1. 创建一个包含样式信息的JSON字符串,其中样式部分需要使用转义字符处理特殊符号。 2. 解析JSON字符串为JavaScript对象。 3. 使用console.log并应用解析后的样式。 例如,考虑以下JSON字符串: "{\"message\": \"%cHello World\", \"style\": \"color: red;\"}" 当解析这个字符串为对象后,调用console.log(obj.message, obj.style)就会输出红色文字。但在这个过程中,JSON中的双引号和反斜杠需要正确转义。 另外,如果用户想直接在JSON字符串中包含ANSI转义码(如在Node.js控制台中),可能需要确保转义字符在字符串中正确表示。例如,ANSI红色文本的转义序列是\x1b[31m,在JSON中需要写成\\x1b[31m,这样解析后的字符串才会包含正确的\x1b[31m。 需要注意的几点: - JSON中反斜杠本身需要转义,所以一个反斜杠在JSON字符串中应写为两个反斜杠\\。 - 浏览器和Node.js的控制台样式支持不同,浏览器用%c加CSS,Node.js可以用ANSI转义码。 - 确保在解析JSON时,转义字符被正确解析,可能需要使用JSON.parse()方法。 可能的误区是,用户可能没有正确转义JSON中的特殊字符,导致解析失败或样式未生效。例如,如果直接在JSON中写"%cHello World"而不处理双引号,会导致JSON格式错误。或者,在字符串中忘记转义反斜杠,使得ANSI码无法正确识别。 因此,解决方案的关键在于正确构造包含转义字符的JSON字符串,确保解析后的字符串能够被控制台正确识别为样式指令。这需要根据目标环境(浏览器或Node.js)选择合适的样式方法,并正确处理JSON中的转义序列。</think>要将包含前端样式的JSON字符串通过转义字符输出到控制台,需要正确处理特殊字符转义和环境适配。以下是分步说明: ```javascript /* 情况一:浏览器环境使用%c占位符 */ // 1. 构造带样式的JSON字符串(注意双引号转义) const jsonStr = '{ "message": "%c这是红色标题", "style": "color: red; font-size: 20px;" }'; // 2. 解析JSON const obj = JSON.parse(jsonStr); // 3. 应用控制台样式输出 console.log(obj.message, obj.style); // 输出红色大字 /* 情况二:Node.js使用ANSI转义码 */ // 1. 构造包含ANSI转义码的JSON(注意双斜杠转义) const ansiJson = '{ "text": "\\x1b[31m红色文字\\x1b[0m" }'; // 2. 解析后直接输出 const ansiObj = JSON.parse(ansiJson); console.log(ansiObj.text); // 输出红色文本 ``` 关键要点: 1. JSON特殊字符转义规则 - 双引号 `"` → `\"` - 反斜杠 `\` → `\\` - 换行符 → `\n` - 制表符 → `\t` 2. 环境差异处理 ```javascript // 浏览器样式方案 const browserStyle = { "template": "%cError: %s", "styles": ["color: red", "color: initial"], "content": ["严重错误", "请检查网络连接"] }; // Node.js样式方案 const nodeStyle = { "message": "\x1b[32mSuccess:\x1b[0m 数据加载完成" }; ``` 3. 安全解析建议 ```javascript function safeParse(jsonStr) { try { return JSON.parse(jsonStr); } catch (e) { console.error('JSON解析失败:', e); return null; } } ``` 常见问题排查: 1. 样式不生效 - 检查转义层级:JSON字符串中的反斜杠需要双重转义(`\\\\` → `\\` → `\`) - 验证控制台支持:Node.js默认不支持%c语法,浏览器不支持ANSI 2. 格式错误 ```javascript // 错误示例:未转义双引号 // "{ "message": "test" }" → 解析失败 // 正确写法 "{ \"message\": \"test\" }" ``` 进阶技巧: ```javascript // 动态样式生成 function createLog(config) { const { message, color = 'black', fontSize = '12px' } = config; console.log(`%c${message}`, `color: ${color}; font-size: ${fontSize};`); } // 使用示例 const configJson = '{"message": "动态样式", "color": "#0099ff", "fontSize": "18px"}'; createLog(JSON.parse(configJson)); ``` 最终输出效果: - 浏览器:显示带自定义样式的格式化消息 - Node.js:显示彩色终端文字 通过正确处理JSON转义规则和目标环境的样式支持机制,即可实现样式化控制台输出。实际开发中建议封装为工具函数,提升代码复用性和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值