微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

跳过顶级 JSON 数据并通过 JavaScript 检索其下方的数据

如何解决跳过顶级 JSON 数据并通过 JavaScript 检索其下方的数据

通过微服务,我检索了几个 JSON 数据包,并将它们输出到 Vue.js 驱动的页面上。数据看起来像这样:

{"data":{"getcompanies":
  [
   {"id":6,"name":"Arena","address":"12 Baker Street","zip":"15090"},{"id":7,"name":"McMillan","address":null,{"id":8,"name":"Ball","address":"342 Farm Road","zip":"15090"}
  ]
 }}

{"data":{"getusers":
  [{"id":22,"name":"Fred","address":"Parmesean Street",{"id":24,"name":"George","address":"Loopy Lane",{"id":25,"name":"Lucy","address":"Farm Road","zip":"15090"}]}}

{"data":{"getdevices":
  [{"id":2,"name":"device type 1"},{"id":4,"name":"device type 2"},{"id":5,"name":"device type 3"}]}}

...我通过这样的代码成功地单独抓取了它们:

getCompanies() {
  this.sendMicroServiceRequest({
    method: 'GET',url: `api/authenticated/function/getcompanies`
  })
  .then((response) => {
    if(response.data) {
      this.dataCompanies = response.data.getcompanies    
    } else {
      console.error(response)
    }
  }).catch(console.error)
}

... getUsers()getDevices() 分别看起来相同。 getCompanies() 返回:

[{"id":6,"zip":"15090"}]

...我将它传递给表格中的 Vue 模板,这很好用。

但如果我需要添加更多微服务调用,这显然会变得笨拙。

我正在寻找一种优雅的方式来跳过 response.data.*whatever* 并通过可重复使用的调用访问那些 id 记录,但我无法到达那里。 response.data[0] 不起作用,映射到我需要的东西要么返回未定义,要么返回数组位。并过滤 response.data[0].id 以仅返回带有 id 的行,不断返回未定义的行。

我最后一次尝试(见下文)访问数据确实有效,但看起来它作为单独的数组元素返回。我宁愿不 - 如果可能的话 - 将数组重建为 JSON 结构。我一直在想,我应该能够跨过下一个级别,不管它叫什么,然后把里面的任何东西都放在一块,就像我直接读response.data.getcompanies一样,但并不在乎'getcompanies' 是什么,或者需要按名称引用它:

// the call
this.dataCompanies = this.getFullData('companies')

getFullData(who) {
  this.sendMicroServiceRequest({
    method: 'GET',url: 'api/authenticated/function/get' + who,})
  .then((response) => {
    if(response) {
      // attempt 1 to get chunk below 'getcompanies'
      Object.keys(response.data).forEach(function(prop) {
        console.log(response.data[prop])
      })
      
      // attempt 2
      // for (const prop in response.data) {
      //  console.log(response.data[prop])
      // }

     let output = response.data[prop]  // erroneously thinking this is in one object
     return output

    } else {
      console.error(response)
    }
  }).catch(console.error)
}

...输出

(63) [{…},{…},{…}]  <-- *there are 63 of these records,I'm just showing the first few...*
0: {"id":6,"zip":"15090"}
1: {"id":7,2: {"id":8,"zip":"15090"}...

哦,上面的 return 由于某种原因在凌晨 3 点让我无法理解。 >.

这是我认为我很接近的事情之一,但并不完全。非常感谢任何正确方向的提示提示或戳。

解决方法

let arrResponse = {data: ['x']};
let objResponse = {data: {getcompanies: 'x'}};

console.log(arrResponse.data[0]);
console.log(Object.values(objResponse.data)[0]);

如果 response.data[0] 是一个数组,

data 会起作用。要获取对象的第一个也是唯一的元素,请改用 Object.values(response.data)[0]Object.values 将对象转换为其值的数组。

其对应的 Object.keysObject.entries 同样分别返回键数组和键值元组。

请注意,对象中的顺序不能保证,因此这只能在您的情况下进行预测,因为 data 恰好只有一个键和值。否则,您必须迭代条目元组并搜索所需条目。

,

firstValue

让我们从通用函数 firstValue 开始。它将获取对象的第一个(如果存在),否则会抛出错误 -

const x = { something: "foo" }
const y = {}

const firstValue = t =>
{ const v = Object.values(t)
  if (v.length)
    return v[0]
  else
    throw Error("empty data")
}

console.log(firstValue(x)) // "foo"
console.log(firstValue(y)) // Error: empty data

获取数据

现在编写一个通用的 getData。我们将 firstValue 函数链接到最后,注意不要在此处添加 console.log.catch;这是调用者决定的选择 -

getData(url) {
  return this
    .sendMicroServiceRequest({ method: "GET",url })
    .then(response => {
      if (response.data)
        return response.data
      else
        return Promise.reject(response)
    })
    .then(firstValue)
}

现在我们写getCompaniesgetUsers等-

getCompanies() {
  return getData("api/authenticated/function/getcompanies")
}

getUsers() {
  return getData("api/authenticated/function/getusers")
}

//...

异步和等待

也许你可以用getDataasync来修饰await -

async getData(url) {
  const response =
    await this.sendMicroServiceRequest({ method: "GET",url })
  return response.data
    ? firstValue(response.data)
    : Promise.reject(response)
}

展示泛型的力量

我们甚至可能会建议不再需要这些 get* 函数 -

async getAll() {
  return {
    companies:
      await getData("api/authenticated/function/getcompanies"),users:
      await getData("api/authenticated/function/getusers"),devices:
      await getData("api/authenticated/function/getdevices"),// ...
  }
}

上面我们使用了三个按顺序发生的 await getData(...) 请求。也许您希望所有这些请求并行运行。下面我们将展示如何做到这一点 -

async getAll() {
  const requests = [
    getData("api/authenticated/function/getcompanies"),getData("api/authenticated/function/getusers"),getData("api/authenticated/function/getdevices")
  ]
  const [companies,users,devices] = Promise.all(requests)
  return { companies,devices }
}

错误处理

最后,错误处理是为调用者保留的,不应在我们的通用函数中尝试 -

this.getAll()
  .then(data => this.render(data)) // some Vue template
  .catch(console.error)
,

我觉得明确访问对象会更好。好像对象键和微服务函数的名字是一致的?如果是这样:

getData(functionName) {
    return this.sendMicroServiceRequest({
        method: 'GET',url: "api/authenticated/function/" + functionName
    })
    .then( response => response.data[functionName] )
}
getCompanies(){
    this.getData("getcompanies").then(companies => {
        this.dataCompanies = companies
    })
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。