如何优化很长的JSON数据?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何优化很长的JSON数据?相关的知识,希望对你有一定的参考价值。

参考技术A 现在主流的网络请求中都采用JSON作为其数据交互格式,这主要是因为JSON有以下优势:

但如果在开发过程中,把很长很大的JSON数据在前后端传输,那就说明设计工作没做好,应该尽量避免这种数据传输,但也可以从下面几个方面进行下优化:

在 Skylake 处理器上,各种解析器解析同一个大数据量的JSON文件的速度(以 GB/s 为单位)如下所示:

我们知道,JSON作为一种轻量级的数据交换格式,现在被广泛应用,特别是在API层,返回数据格式基本上都是JSON。但是, JSON字符串如果过长,那在网络传输中也存在耗时的 ,站在性能角度我们需要合理优化JSON。

1、服务器端 开启GZip压缩

主流的服务端都支持GZip压缩,对于一般的纯文本内容GZip压缩率在35%以上,这样做的好处也很明显:

2、 键名缩短

对于结果集而言,数据都是查询循环输出的,所以当我们把键名缩短也变相压缩了JSON文本长度。比如原本的 "name":"张三" 我们可以写为 "a":"张三"

3、JSON中的 中文避免被转为Unicode编码

现在也有不少人喜欢将JSON中的汉字转为Unicode编码,此时JSON文本内容就会变得很长,如果避免汉字转码,可以控制文本长度。

1,开启gzip,压缩率很高,即便是很长的文本,在网络中传输量也很小 。

2,不建议分次请求,除非是业务需要。连接次数过多,加大了并发的压力。

3,提醒用户点击的做法可以通过按钮反馈或loading条来做。

4,如果有可能,考虑提前预读你可以这样,在一个隐藏的 iframe 里面请求服务器,返回值是这样的: <script> parent.notifyDataArrive(YOURS_JSON_DATA); </script>

从 JSON 中提取很长的字符串到 CLOB

【中文标题】从 JSON 中提取很长的字符串到 CLOB【英文标题】:Extracting very long string from JSON to CLOB 【发布时间】:2017-07-24 09:57:50 【问题描述】:

我正在尝试从 json_object_t 将一个很长的字符串提取到 clob 中,并使用 json_object_t.get_clob(key) 方法获得了一些奇怪的数据库行为 (12.2c)。 有一个示例代码比以下:

DECLARE
  l_data CLOB := '"text": "very long string about 1M chars"';
  l_json json_object_t;
  l_text CLOB := EMPTY_CLOB();
BEGIN
  l_json := json_object_t.parse(l_data);
  l_text := l_json.get_clob('text');
  dbms_output.put_line('got ' || dbms_lob.getlength(l_text) || ' chars');
END;

当 'text' 键中的字符串长度小于 32k 字符时,get_clob 方法可以正常工作并显示适当的结果,但是对于较长的字符串,它会产生一个长度为零的空 clob,就像 get_string 一样,但没有 'character string缓冲区太小”异常。

我尝试通过 json_table 查询获取相同的数据,但它根本无法将数据提取到 clob 列,只允许使用 varchar/number。

这是一个错误还是我做错了什么?还有其他方法可以从 JSON 键中提取长字符串吗?

【问题讨论】:

【参考方案1】:

我与 Oracle 数据库 JSON 存储组合作,很乐意帮助您解决您面临的这个问题。您能否尝试使用备用 get_Clob 过程而不是此函数并告诉我们行为是什么?

签名:

MEMBER PROCEDURE get_Clob(key VARCHAR2, c IN OUT CLOB)

请试试这个:

DECLARE
    content_json CLOB := '"value":"';
    content_json_end CLOB := '"';
    content_tmp CLOB := 'ab';
    l_json json_object_t;
     l_text CLOB := EMPTY_CLOB();
    tmp clob;
BEGIN
    -- 13 gives 16K
    -- 14 gives 32K
    FOR count IN 1 .. 14
    loop
        dbms_lob.append(content_tmp, content_tmp);  -- a bad append for now
    END loop;

    dbms_lob.append(content_json, content_tmp);
    dbms_lob.append(content_json, content_json_end);

    l_json := json_object_t.parse(content_json);
    l_json.get_clob('value', l_text); -- !!! TRY THIS PROC get_Clob
    --l_text := l_json.get_clob('value');

    dbms_output.put_line('Lob size in Kb: ');
    dbms_output.put_line(dbms_lob.getLength(l_text) / 1024);
END;
/ 

期待你的发现..

【讨论】:

您好,只是想与您核实一下。您是否尝试过其他方法?有效果吗? 唉,同样的结果:Lob size in Kb: 0. 此外,get_blob 工作正常 - livesql.oracle.com/apex/livesql/file/… Caine,我是开发 JSON_OBJECT_T 等方法的人。不幸的是,我无法重现您的问题(也尝试了几个早期版本)。请向我提供以下信息:1)您使用什么数据库字符集 SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET' ; 2)您使用什么版本的数据库?从 V$INSTANCE 中选择版本; 现在已经在 ALF32UTF8 字符集的 12.2.0.1 数据库版本上重现了。与此同时,我们已经解决了这个问题。请联系 Oracle 支持以获取您的数据库版本的反向移植。谢谢你。【参考方案2】:

这也有效。而不是使用get_clob 方法,而是使用c

DECLARE

   CURSOR crsrJSON IS
   SELECT 
       json_object( 'employee_id'     VALUE employee_id,
                    'first_name'      VALUE first_name,
                    'last_name'       VALUE last_name,
                    'email'           VALUE email,
                    'phone_number'    VALUE phone_number,
                    'hire_date'       VALUE to_char(hire_date,'MM/DD/YYYY'),
                    'job_id'          VALUE job_id,
                    'salary'          VALUE nvl(salary,0),
                    'commission_pct'  VALUE nvl(commission_pct,0),
                    'manager_id'      VALUE NVL(manager_id,0),
                    'department_id'   VALUE NVL(department_id,0), 
                    'department_name' VALUE (select department_name from departments x where x.department_id = hr.department_id), 
                    'job_title'       VALUE (select job_title from jobs x where x.job_id = hr.job_id)) emp_data
    FROM 
           employees hr;

    js_array JSON_ARRAY_T := new JSON_ARRAY_T;

    json_obj  JSON_OBJECT_T := JSON_OBJECT_T();

    json_clob CLOB := EMPTY_CLOB();

BEGIN

   FOR data_rec IN crsrJSON LOOP

     js_array.append(JSON_ELEMENT_T.parse(data_rec.emp_data));

   END LOOP;

   json_obj.put('data',js_array);



   IF json_obj.has('data') THEN

      json_clob := json_obj.to_clob;
      DBMS_OUTPUT.PUT_LINE(json_clob);


   ELSE

     DBMS_OUTPUT.PUT_LINE('Nope');

   END IF;

END;

【讨论】:

如果你想提取一个长键值,这也适用(与我的示例代码相关): (json_elem JSON_ELEMENT_T;) json_elem := json_obj.get('data'); DBMS_OUTPUT.PUT_LINE(json_elem.to_clob);【参考方案3】:
with data as
  ( select 
    xmlelement(e,regexp_replace('"name":"'||colname||'"', '[[:cntrl:]]', ''),',') col1
    from tblname
  )
  select
        rtrim(replace(replace(replace(xmlagg(col1).getclobval(),'&'||'quot;','"'),'<E>',''),'</E>',''),',')
        as very_long_json
  from data;

【讨论】:

只要执行你就会找到你梦想中的 json :D

以上是关于如何优化很长的JSON数据?的主要内容,如果未能解决你的问题,请参考以下文章

Swifty Json 变得不为人知但很长的路很好用?

从 JSON 中提取很长的字符串到 CLOB

iOS开发之JSON格式数据的生成与解析

OC之JSON数据解析

Android java xml到json很长

将 JSON 数据嵌套到 Datatable 中不起作用