通过 php 脚本将 Google-Sheet fed json 字符串转换为具有内插键默认值的数组

converting a Google-Sheet fed json string into an array with interpolated key default values via php script

我有一个来自常规 Google Sheet 文档的 json 输出(在 之后)输出正是这种格式

{
  "range": "json!A1:Y1000",
  "majorDimension": "ROWS",
  "values": [
    [
      "nome",
      "cognome",
      "salary",
      "assunzione",
      "location",
      "extension"
    ],
    [
      "james",
      "di marcio",
      ",675",
      "09/12/2009",
      "San Francisco",
      "5384"
    ],
    [
      "marco",
      "giaccanti",
      ",560",
      "06/06/2020",
      "roma",
      "5385"
    ]
  ]
}

并且需要转换成这个非常格式

{
  "data": [
    {
      "id": "1",
      "name": "Tiger Nixon",
      "position": "System Architect",
      "salary": "0,800",
      "start_date": "2011/04/25",
      "office": "Edinburgh",
      "extn": "5421"
    },
    {
      "id": "2",
      "name": "Frank Major",
      "position": "top manager",
      "salary": "0,800",
      "start_date": "2011/06/20",
      "office": "San Francisco",
      "extn": "5221"
    }
  ]
}

以便在 this Datatables project 内可用。

我能想到的最好的解决方案是这个解决方案,它当然不符合要求的模式并且只适用于嵌套在“值”中的第一个数组,而它需要将它们全部转换:

 <?php
$json   = file_get_contents('https://sheets.googleapis.com/v4/spreadsheets/[my_sheet_id]/values/json?key=[my_api_key]');
$objs   = json_decode($json, false);
$codes  = $objs->values[0];
$names  = $objs->values[1];


foreach( $codes as $index => $code ) {
   echo  $code. ': ' . $names[$index]." ";
}
?>
nome: james cognome: di marcio salary: ,675 assunzione: 09/12/2009 location: San Francisco extension: 5384 

我们的想法是自动将第一个数组值设置为循环值的键,但是当然代码还不够..

有什么建议吗?

一个侧面的考虑:Datatables 不关心 table 提供的是哪种文件。您可以选择 .txt 文件和 .php 文件,或者我认为甚至可以选择 .js 文件。
可能有点幼稚,我认为 .php 是最好的解决方案,因为 - 我认为 - 处理工作是在服务器端而不是客户端完成的,因此可能会更快。是这样吗?

ps:对于重复搜索者,我在发布前检查了不同的来源,none 确实适合我的情况

其实比你想象的要简单,

$originalArray = json_decode($json, true);

$keys = ["id", "name", "position", "salary", "start_date", "office", "extn"];
$rows = array_slice($originalArray['values'], 1);

$data = [];
foreach($rows as $i => $row) {
    array_unshift($row, (string)($i + 1));
    
    $data[] = array_combine($keys, $row);
}

$output = json_encode(["data" => $data]);

过程首先,我们解码json得到对应的关联数组:

$originalArray = json_decode($json, true);

然后我们定义要分配给每条记录的键:

$keys = ["id", "name", "position", "salary", "start_date", "office", "extn"];

然后我们提取包含数据的实际记录,这些数据从 $originalArray.

中的键 values 的索引 1 开始
$rows = array_slice($originalArray['values'], 1);

现在我们的记录都是如下值:

    [
      "james",
      "di marcio",
      ",675",
      "09/12/2009",
      "San Francisco",
      "5384"
    ]

我们需要将上面的值与之前对应的 $keys 结合起来。我们遍历所有记录 $rows 并为它们分配键。我们使用 PHP 的函数 array_combine,它接受两个具有相同长度的数组输入,第一个用作 keys,第二个用作 values 然后组合它们。

但我们必须注意,我们的值记录本身没有 id 值,因此我们必须将这些值与一个额外的类似索引的 id 字段合并。所以我们使用 array_unshift 添加索引作为数组 $row 的第一个元素(我们也将其转换为字符串)。所以代码变成:

$data = [];
foreach($rows as $i => $row) {
    array_unshift($row, (string)($i + 1));
    
    $data[] = array_combine($keys, $row);
}

注意:array_unshift 接受数组 $row 作为引用类型并更改它。

现在的输出是这样的:

[
    id=> "1",
    name=> "james",
    position=> "di marcio",
    salary=> ",675",
    start_date=> "09/12/2009",
    office=> "San Francisco",
    extn=> "5384"
]

最后我们需要将这个关联数组编码为 json 和 return 它,我们还必须为它制作一个名为 data 的键,所以:

$output = json_encode(["data" => $data]);

output变为:

{
    "data": [
        {
            "id": "1",
            "name": "james",
            "position": "di marcio",
            "salary": ",675",
            "start_date": "09/12/2009",
            "office": "San Francisco",
            "extn": "5384"
        },
        {
            "id": "2",
            "name": "marco",
            "position": "giaccanti",
            "salary": ",560",
            "start_date": "06/06/2020",
            "office": "roma",
            "extn": "5385"
        }
    ]
}
$json   = file_get_contents('https://sheets.googleapis.com/v4/spreadsheets/[my_sheet_id]/values/json?key=[my_api_key]');
$objs  = json_decode($json, false);

// Set the header
$codes = $objs->values[0];

// Unset header values
unset($objs->values[0]);

// Loop the rows
foreach( $objs->values as $key => $jsonRow ) {
    // Create a line to add with id field
    $lineToAdd['id'] = $key;
    // Add values from the row
    foreach ( $codes as $codeKey => $code ) {
        $lineToAdd[$code] = $jsonRow[$codeKey];
    }
   $data[] = $lineToAdd;
}

这是一个脚本,它执行从数组数组到 objects 数组的基本转换:

let sourceFormat = {
  "range": "json!A1:Y1000",
  "majorDimension": "ROWS",
  "values": [
    [
      "nome",
      "cognome",
      "salary",
      "assunzione",
      "location",
      "extension"
    ],
    [
      "james",
      "di marcio",
      ",675",
      "09/12/2009",
      "San Francisco",
      "5384"
    ],
    [
      "marco",
      "giaccanti",
      ",560",
      "06/06/2020",
      "roma",
      "5385"
    ]
  ]
};

let targetFormat = [];

let headings = sourceFormat.values.slice(0, 1)[0];

sourceFormat.values.slice(1).forEach((row) => { 
  let rowObject = {};
  row.forEach((item, index) => {
    var name = headings[index];
    rowObject[name] = item;
  } )
  targetFormat.push ( rowObject );
} )

console.log( { "data" : targetFormat } );

您可以添加 console.log() 语句以查看每一步发生的情况,但这里有一个演练:

首先,我们将标题视为一个单独的数组:

sourceFormat.values.slice(0, 1)[0]

然后将数组数组的剩余部分作为您的数据行:

sourceFormat.values.slice(1)

然后我们遍历每个数组,并为每个数组构建一个 object:

sourceFormat.values.slice(1).forEach((row) => { ... } )

我们使用每个内部数组的索引位置来查找相关标题名称:

var name = headings[index];

然后我们开始将条目添加到我们的(最初为空 let rowObject = {};)行 object:

rowObject[name] = item;

上面一行是在每个 object 中构建每个 name/value 对的内容。

我们将每个新的 object 推入一个新数组:

targetFormat.push ( rowObject );

最后,我们将所有东西都包裹在一个最终的外部 object:

{ "data" : targetFormat }

结果是这样的:

{
  "data": [
    {
      "nome": "james",
      "cognome": "di marcio",
      "salary": ",675",
      "assunzione": "09/12/2009",
      "location": "San Francisco",
      "extension": "5384"
    },
    {
      "nome": "marco",
      "cognome": "giaccanti",
      "salary": ",560",
      "assunzione": "06/06/2020",
      "location": "roma",
      "extension": "5385"
    }
  ]
}