我的编程空间,编程开发者的网络收藏夹
学习永远不晚

解析多个 JSON 数组中的实体,消除重复代码

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

解析多个 JSON 数组中的实体,消除重复代码

小伙伴们对Golang编程感兴趣吗?是否正在学习相关知识点?如果是,那么本文《解析多个 JSON 数组中的实体,消除重复代码》,就很适合你,本篇文章讲解的知识点主要包括。在之后的文章中也会多多分享相关知识点,希望对大家的知识积累有所帮助!

问题内容

我正在制作一个 json api 包装器客户端,它需要获取分页结果,其中下一页的 url 由上一页提供。为了减少共享相同响应格式的 100 多个实体的代码重复,我希望有一个客户端方法来从所有分页页面获取和解组不同的实体。

我当前的简化(伪)版本方法(没有错误等):

type ListResponse struct {
    Data struct {
        Results []interface{} `json:"results"`
        Next    string        `json:"__next"`
    } `json:"d"`
}

func (c *Client) ListRequest(uri string) listResponse ListResponse {
    // Do a http request to uri and get the body
    body := []byte(`{ "d": { "__next": "URL", "results": []}}`)
    json.NewDecoder(body).Decode(&listResponse)
}

func (c *Client) ListRequestAll(uri string, v interface{}) {
    a := []interface{}
    f := c.ListRequest(uri)
    a = append(a, f.Data.Results...)

    var next = f.Data.Next
    for next != "" {
        r := c.ListRequest(next)
        a = append(a, r.Data.Results...)
        next = r.Data.Next
    }

    b, _ := json.Marshal(a)
    json.Unmarshal(b, v)
}

// Then in a method requesting all results for a single entity
var entities []Entity1
client.ListRequestAll("https://foo.bar/entities1.json", &entities)

// and somewehere else
var entities []Entity2
client.ListRequestAll("https://foo.bar/entities2.json", &entities)

然而,问题是这种方法效率低下并且使用太多内存等,即首先在通用 listresponse 中进行解组,结果为 []interface{} (以查看下一个 url 并将结果连接到单个切片中) ),然后编组 []interface{},以便在 []entity1 的目标切片中直接向后解编它。

我也许可以使用 reflect 包动态创建这些实体的新切片,直接解组到它们中并随后连接/附加它们,但是如果我理解正确,我最好不要使用 reflect 除非绝对必要...

解决方案


查看 encoding/json 包中的 rawmessage 类型。它允许您将 json 值的解码推迟到以后。例如:

results []json.rawmessage `json:"results"`

甚至...

results json.rawmessage `json:"results"`

由于 json.rawmessage 只是一个字节片段,因此这比您要解组到的中间 []interface{} 效率更高。

关于如何在给定多页读取的情况下将它们组装成单个切片的第二部分,您可以通过让调用者使用切片类型的切片来将该问题转嫁给调用者。

// then in a method requesting all results for a single entity
var entitypages [][]entity1
client.listrequestall("https://foo.bar/entities1.json", &entitypages)

但是,这仍然存在您的一般设计所存在的无限内存消耗问题,因为您必须立即加载所有页面/项目。您可能需要考虑更改为打开/读取抽象,例如处理文件。您将有一些 open 方法,该方法返回另一种类型,例如 os.file,提供一次读取数据子集的方法,同时在内部请求页面并根据需要进行缓冲。

也许是这样的(未经测试):

type PagedReader struct {
  c *Client

  buffer []json.RawMessage

  next string
}

func (r *PagedReader) getPage() {
  f := r.c.ListRequest(r.next)
  r.next = f.Data.Next
  r.buffer = append(r.buffer, f.Data.Results...)
}

func (r *PagedReader) ReadItems(output []interface{}) int {
  for len(output) > len(buffer) && r.next != "" {
    r.getPage()
  }

  n := 0
  for i:=0;i<len(output)&&i< len(r.buffer);i++ {
    json.Unmarshal(r.buffer[i], output[i] )
    n++
  }
  r.buffer = r.buffer[n:]
  return n
}

今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注编程网公众号,一起学习编程~

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

解析多个 JSON 数组中的实体,消除重复代码

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

解析多个 JSON 数组中的实体,消除重复代码

小伙伴们对Golang编程感兴趣吗?是否正在学习相关知识点?如果是,那么本文《解析多个 JSON 数组中的实体,消除重复代码》,就很适合你,本篇文章讲解的知识点主要包括。在之后的文章中也会多多分享相关知识点,希望对大家的知识积累有所帮助!问
解析多个 JSON 数组中的实体,消除重复代码
2024-04-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录