【问题标题】:How to parse this JSON object/string?如何解析这个 JSON 对象/字符串?
【发布时间】:2014-07-28 15:08:15
【问题描述】:

我正在尝试解析写入@http://a0.awsstatic.com/pricing/1/ec2/sles-od.min.js的JSON

这是来自上述链接的快速 sn-p:

{vers:0.01,config:{rate:"perhr",valueColumns:["vCPU","ECU","memoryGiB","storageGB","sles"],currencies:["USD"],regions:[{region:"us-east",instanceTypes:[{type:"generalCurrentGen",sizes:[{size:"t2.micro",vCPU:"1",ECU:"variable",
...
...
...
...

请访问上述链接以查看完整的 JSON。

如上所示,上述 JSON 的 keys 都没有双引号

这会导致 JSON 字符串格式错误,并且我的 JSON 解析器无法处理它。我还尝试将此 JSON 放入 http://www.jsoneditoronline.org/ 中,但它也失败了。

现在,这是亚马逊用来显示其 EC2 实例的各种价格的同一个链接。所以我想我在这里遗漏了一些东西。我的谷歌搜索让我相信上面的东西不是JSON,而是JSONP..我不明白那是什么。

你能帮我理解如何解析这个 JSON。顺便说一句,我正在使用JSON Module 做这项工作。

一些背景:

Amazon Web Services 没有以编程方式获取定价信息的 API。因此,我正在解析这些链接,这是亚马逊在显示定价信息here 时所做的事情。此外,我不是编程领域的,我只知道perl

【问题讨论】:

  • “此文件仅供在 aws.amazon.com 上使用。”您确定没有其他 API 可以满足您的需求吗?
  • 不,亚马逊不提供获取价格信息的 API。因此,很多人都做了类似的事情来解析这些链接。但是,它们中的大多数都在 python/ruby 中。我正在尝试使用 perl。
  • 不是 JSON,sles-od.min.js 包含 JavaScript。
  • 是的,它不是 JSON,所以你不能使用 JSON 解析器。你需要一个 JS 解析器。但幸运的是,该程序使用了一小部分可预测的 JS 子集,因此您也不必编写完整的 JS 解析器。 // 尝试添加引号是没有意义的。你需要解析它才能做到这一点。如果你能做到这一点,那么就没有必要解析它了。

标签: perl json perl amazon-web-services


【解决方案1】:

就像你说的 JSONP 或“带填充的 JSON”不能被 json 解析器解析,因为它不是 json(它是一种不同的格式)。但它实际上是一个带有前缀(填充)的json

填充通常是包装 json 的回调函数的名称。

在这种情况下,它的默认回调名称为'callback',我们可以通过使用正则表达式来捕获由'callback()'包装的json,就像这样

s/callback\((.*)\);$/$1/s;

另外,如果您想使用 JSON 库,您可以启用 allow_barekey,这意味着您不需要这些键周围的引号。

以下是我的工作代码。我使用LWP::Simple 获取给定的内容,使用Data::Dump 打印隔离的数据结构。

use strict;
use warnings;

use LWP::Simple;
use JSON;

my $jsonp = get("http://a0.awsstatic.com/pricing/1/ec2/sles-od.min.js")
    or die "Couldn't get url";

( my $json = $jsonp ) =~ s/callback\((.*)\);$/$1/s; #grap the json from $jsonp and store in $json variable
my $hash = JSON->new->allow_barekey->decode ( $json );

use Data::Dump;
dd $hash;

输出:

{
  config => {
              currencies => ["USD"],
              rate => "perhr",
              regions => [
                {
                  instanceTypes => [
                    {
                      sizes => [
                                 {
                                   ECU => "variable",
                                   memoryGiB => 1,
                                   size => "t2.micro",
                                   storageGB => "ebsonly",
                                   valueColumns => [{ name => "os", prices => { USD => 0.023 } }],
                                   vCPU => 1,
                                 },
                                 {
                                   ECU => "variable",
                                   memoryGiB => 2,
                                   size => "t2.small",
                                   storageGB => "ebsonly",
                                   valueColumns => [{ name => "os", prices => { USD => 0.056 } }],
                                   vCPU => 1,
                                 },
                                 {
                                   ECU => "variable",
                                   memoryGiB => 4,
                                   size => "t2.medium",
                                   storageGB => "ebsonly",
                                   valueColumns => [{ name => "os", prices => { USD => 0.152 } }],
                                   vCPU => 2,
                                 },
                                 {
                                   ECU => 3,
                                   memoryGiB => 3.75,
                                   size => "m3.medium",
                                   storageGB => "1 x 4 SSD",
                                   valueColumns => [{ name => "os", prices => { USD => "0.170" } }],
                                   vCPU => 1,
                                 },
....

【讨论】:

    【解决方案2】:

    正如上面的 cmets 所说,它不是 JSON 所以它不能被 JSON 解析器解析...但是对于一个 快速和(非常)脏的工作,你可以试试JSON::DWIW 模块。

    下一个代码:

    use 5.014;
    use warnings;
    use WWW::Mechanize;
    use Data::Dump;
    
    use JSON::DWIW;
    
    my $mech = WWW::Mechanize->new();
    my $jsonstr = $mech->get('http://a0.awsstatic.com/pricing/1/ec2/sles-od.min.js')->content;
    ($jsonstr) = $jsonstr =~ /callback\((.*)\)/s;
    
    my $json_obj = JSON::DWIW->new;
    my $data = $json_obj->from_json( $jsonstr );
    dd $data;
    

    打印一个可能是你想要的结构,例如:

    {
      config => {
                  currencies => ["USD"],
                  rate => "perhr",
                  regions => [
                    {
                      instanceTypes => [
                        {
                          sizes => [
                                     {
                                       ECU => "variable",
                                       memoryGiB => 1,
                                       size => "t2.micro",
                                       storageGB => "ebsonly",
                                       valueColumns => [{ name => "os", prices => { USD => 0.023 } }],
                                       vCPU => 1,
                                     },
                                     {
    

    【讨论】:

    • 非常感谢。我不知道DWIW。你的回答回答了我的问题。但是,我会接受“ZDK”的回答,因为它可以节省我安装新模块的时间。为您的时间 +1。
    • @slayedbylucifer 他的回答更好,我刚刚了解了allow_barekey。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2020-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多