HarmonyOS 超长JSON字符串解析

在实际的项目中将后台配置的JSON字符串下载在手机中(其他系统是用的SP存储)然后进行解析,拿到里面的内容。

在HarmonyOS 中,初期计划下载下来用首选项进行存储,但了解到首选项存储不料这么长的字符串。所以存储成了文件。

当前困难影响:

在获取文件中内容 时,我定义了

@State jsGlobalConfig:string=''

在while中来进行接收

this.jsGlobalConfig = this.jsGlobalConfig+value.toString()

但报错了:

[nodict][common_func.cpp:122->GetActualLen] Invalid option.length
[nodict][common_func.cpp:371->GetReadArg] Failed to get actual length
[nodict][prop_n_exporter.cpp:388->ReadSync] Failed to resolve buf and options
 [nodict][ecmascript] Pending exception before IsMixedDebugEnabled called in line:3320, exception details as follows:
 [nodict]Error: Invalid argument

不知道是因为string的长度有限,不能存储太长的字符串还是因为什么。

1、我应该用什么来接收超长JSON字符串

2、如何进行解析,拿到里面的数据。

以下是我们项目中的部分解析代码。

String jsGlobalConfig = “实际获取到的超长JSON字符串”
JSONObject jsonObject = new JSONObject(jsGlobalConfig);
JSONArray pagesArray = jsonObject.optJSONArray("pages");
String pathname = getUrlSubstring(pathName);

String matchUrl = "";

for (int i = 0; i < pagesArray.length(); i++) {
  if (pathname.equals(pagesArray.get(i).toString())) {
    matchUrl = pagesArray.get(i).toString();
    break;
  }
}
JSONObject rulesObject = jsonObject.optJSONObject("rules");
JSONObject targetObject = rulesObject.optJSONObject(matchUrl);
String navigationBarBackgroundColor = targetObject.optString("navigationBarBackgroundColor");

//获取URL 中的路由进行精准匹配
public String getUrlSubstring(String url) {
  if (url.contains(AnDunServiceGenerator.FORMAL_PATH)) {
    //站内链接
    String baseString = AnDunServiceGenerator.FORMAL_PATH;
    int comIndex = url.indexOf(baseString) + baseString.length();

    if (url.contains("?")) {
      int questionMarkIndex = url.indexOf("?");
      return url.substring(comIndex, questionMarkIndex);
    } else {
      return url.substring(comIndex);
    }
  } else {
    //站外链接 //eg:https://www.huawei.com/cn/?ic_medium=direct&ic_source=surlent
    return "";
  }

}
HarmonyOS
17h前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
Heiang

参考如下demo,日志过长需要进行分段打印:

import { BusinessError, request } from '@kit.BasicServicesKit';
import fs from '@ohos.file.fs';
import common from '@ohos.app.ability.common';
import buffer from '@ohos.buffer';
import util from '@ohos.util';
import { JSON } from '@kit.ArkTS';

// 获取应用文件路径
let context = getContext(this) as common.UIAbilityContext;
let filesDir = context.filesDir;

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  @State jsonStr: string = '';

  async download() {
    let config: request.agent.Config = {
      action: request.agent.Action.DOWNLOAD,
      url: 'https://app-demo.iandun.com/settings.json?v=1718157761736', // 需要手动将 url 替换为真实服务器的 HTTP 协议地址
      overwrite: true,
      saveas: filesDir + '/jsonStr.text' // 存储地址
    };
    try {
      request.agent.create(context, config).then((task: request.agent.Task) => {
        console.info(`Succeeded in creating a download task. result: ${task.config}`);
        console.info("存储地址:" + filesDir + '/jsonStr.text');
        task.start();
      }).catch((err: BusinessError) => {
        console.error(`Failed to create a download task, Code: ${err.code}, message: ${err.message}`);
      });
    } catch (e) {
      console.log(JSON.stringify(e))
    }
  }

  async readLocalFileWithStream(path: string) {
    try {
      // 存储每次读取的结果
      let buffers: buffer.Buffer[] = [];
      // 打开文件流
      let inputStream = fs.createStreamSync(path, 'r+');
      // 以流的形式读取源文件内容
      let bufSize = 4096;
      let readSize = 0;
      let buf = new ArrayBuffer(bufSize);

      class Option {
        public offset: number = 0;
        public length: number = bufSize;
      }

      let option = new Option();
      option.offset = readSize;
      let readLen = await inputStream.read(buf,
        option);
      // 存储当前读取结果
      buffers.push(buffer.from(buf.slice(0, readLen)))
      readSize += readLen;
      while (readLen > 0) {
        option.offset = readSize;
        readLen = await inputStream.read(buf,
          option);
        // 存储当前读取结果
        buffers.push(buffer.from(buf.slice(0, readLen)))
        readSize += readLen;
      }
      // 关闭文件流
      inputStream.closeSync();

      // 合并内容
      let finalBuf: ArrayBuffer = buffer.concat(buffers).buffer
      console.info(`final ArrayBuffer byteLength is ${finalBuf.byteLength}}`)
      // ArrayBuffer转string
      let textDecoder = util.TextDecoder.create('utf-8');
      let finalUnit = new Uint8Array(finalBuf)
      this.jsonStr = textDecoder.decodeWithStream(finalUnit)
      console.info(`final str Length is ${this.jsonStr.length}}`)
      // 修改打印日志输出大小, IDE控制台日志输出的设置:File->setting->Editor->general->Console下,有个override console cycle buffer size选项
      // 仍然超过需要分段打印
      console.info('final str is ' + this.jsonStr)
    } catch (error) {
      let err = error as BusinessError;
      console.error(`readLocalFileWithStream failed, code is ${err.code},message is ${err.message}`);
    }
  }

  build() {
    Column() {
      Text(this.message)
        .id('DownloadPageHelloWorld')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .onClick(() => {
          this.download()
        })
      Text("获取json")
        .id('DownloadPageHelloWorld')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .onClick(() => {
          this.readLocalFileWithStream(filesDir + '/jsonStr.text')
        })
    }
  }
}
分享
微博
QQ
微信
回复
15h前
相关问题
HarmonyOS 如何解析json字符串
590浏览 • 1回复 待解决
如何解析JSON字符串
1277浏览 • 1回复 待解决
嵌套JSON字符串解析问题
2071浏览 • 1回复 待解决
HarmonyOS 服务端JSON字符串解析问题
593浏览 • 1回复 待解决
如何打印JSON对象和JSON字符串
404浏览 • 1回复 待解决
如何实现Map转JSON字符串
1142浏览 • 1回复 待解决
Web组件接收超长字符串时会被截断
271浏览 • 1回复 待解决
如何将对象转为JSON字符串
599浏览 • 1回复 待解决
怎么动态组装一个json字符串
297浏览 • 1回复 待解决
如何将JSON字符串转Class对象
489浏览 • 1回复 待解决
如何将JSON字符串转为Map
341浏览 • 1回复 待解决
HarmonyOS json解析特殊字符
24浏览 • 1回复 待解决
检查字符串是否以给定的字符串开头
549浏览 • 1回复 待解决
HarmonyOS字符串替换问题
908浏览 • 1回复 待解决