【问题标题】:Parsing nested array of unknown depth解析未知深度的嵌套数组
【发布时间】:2016-04-30 09:38:26
【问题描述】:

我从第三方获取 json 文件,其中键值对的深度可变,类似于: *** 编辑 JSON 以阐明将在 mysql db 中使用的表名。键是表中的列,值是数据。从 json 到 json 的列名将是静态的。

   {                         
   "Key1": "Value1",  //non-nested key:value go to default table                     
   "Key2": "Value2",                      
   "Key3": "Value3",                                 
   "Table1": [],                      
   "Table2": [{                      
        "Key1": "Value1",                  
        "Key2": "Value2",                  
        "Key3": "Value3"},

        {"Key1": "Value1",                  
         "Key2": "Value2",                  
         "Key3": "Value3"}],

    "Table3": [
          {"Key1": "Value1",                  
            "Key2": "Value2",                  
            "Key3": "Value3"},
             {"Table4": [
                   {"Key1": "Value1",              
                    "Key2": "Value2",              
                    "Key3": "Value3"},
                {"Table5": [
                           {"Key1": "Value1",          
                            "Key2": "Value2",          
                            "Key3": "Value3"}]
                 }]
           }]    
     }

** 此示例通过 JSON 验证

对于初始键:值对(不在嵌套数组中),我需要设置一个表名,将所有非嵌套值插入表中。对于嵌套的 Key:Value 对,需要将表名设置为 Array 键,即 Array1、Array2、Array3 等,其中嵌套的 Key 为列名,Value 为数据。

我一直在尝试使用 RecursiveIteratorIterator 重申数组(我知道这比数组的嵌套 foreach 处理有一些速度优势)但无论哪种方式..我在分离嵌套数组和拉出底层数组时遇到了麻烦键:值。

我正在尝试这个:

$iterator = new RecursiveIteratorIterator(
    new RecursiveArrayIterator($data1),
    RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $key=>$value){
        if (!is_array($value)){
        //echo $key." KEY is not an array <br>";
        }

        if(is_array($value)){
            //echo $key." KEY is an array <br>";
                foreach($value as $key1=>$val1){
                    if (is_array($val1)){
                    //echo $key1."KEY 1 is an array<br>";  
                }
            }    
        }
    }    

更新

用户@olibiaz 提出了一个几乎 100% 正确的解决方案:

function toto(array $input, $tableName = '')
{
    foreach ($input as $key => $element) {
      if (is_array($element)) {
         toto($element, $key);
      } else {
          if ($tableName === '') {
             // here is the non nested elelement,
             // you can choose the tableName you want
             $tableName = 'NonNestedTableName';
          }
          // place your insert here or whatever you want
          // here, the tablename is the index of the nested array
          echo "TableName: $tableName, Key: $key, Data: $element \n";
      }
    }
}

这是在我的 JSON 数据上运行上述代码时得到的输出:

TableName: project, Key: Key1, Data: Value1 // "project" used for non-nested
TableName: project, Key: Key2, Data: Value2 
TableName: project, Key: Key3, Data: Value3
TableName: 0, Key: Key1, Data: Value1  // Tablename needs to be "Array2"
TableName: 0, Key: Key2, Data: Value2  // for these 3 data sets
TableName: 0, Key: Key3, Data: Value3 
TableName: 1, Key: Key1, Data: Value1  // Tablename needs to be "Array2"
TableName: 1, Key: Key2, Data: Value2 
TableName: 1, Key: Key3, Data: Value3 
TableName: 0, Key: Key1, Data: Value1  // Tablename needs to be "Array3"
TableName: 0, Key: Key2, Data: Value2 
TableName: 0, Key: Key3, Data: Value3  
TableName: 0, Key: Key1, Data: Value1  // Tablename needs to be "Array4"
TableName: 0, Key: Key2, Data: Value2 
TableName: 0, Key: Key3, Data: Value3 
TableName: 0, Key: Key1, Data: Value1  // Tablename needs to be "Array5"
TableName: 0, Key: Key2, Data: Value2 
TableName: 0, Key: Key3, Data: Value3

但是,我需要使用数组的键名,而不是使用数字索引作为表名。也许 olibiaz 或其他用户对如何实现这一点有建议?

【问题讨论】:

  • 您的 JSON 多处缺少逗号,缩进不一致。您能否修复它以便我们了解它的结构?
  • 我可以——但这与这个问题有密切关系吗?我认为要传达的重要信息是它是嵌套的、未知的深度,并且初始键:值对不是嵌套数组的一部分,而是数组的顶层。我知道该示例不会通过 JSON 验证,但它只是为了说明。
  • 现在有嵌套的错觉,其实Array1Array2等都是顶层对象的成员。我不确定这是否是故意的。在对很多结构没有硬编码的算法中,重要的是我们知道哪些结构是可选的。
  • 你为什么不用这个:json_decode($object, true);
  • @Mojtaba - 我正在使用 json_decode 将对象转换为 $data1 数组,谢谢!

标签: php json


【解决方案1】:

在所有 cmets 和交流之后编辑。我会更准确地举你的例子

<?php

$inputJson = '{                         
   "Key1": "Value1",                      
   "Key2": "Value2",                      
   "Key3": "Value3",                                 
   "Table1": [],                      
   "Table2": [{                      
      "Key1": "Value1",                  
      "Key2": "Value2",                  
      "Key3": "Value3"},
     {
        "Key1": "Value1",                  
        "Key2": "Value2",                  
        "Key3": "Value3"}],
   "Table3": [{
        "Key1": "Value1",                  
        "Key2": "Value2",                  
        "Key3": "Value3"},
         {
           "Table4": [{
              "Key1": "Value1",              
              "Key2": "Value2",              
              "Key3": "Value3"},
           {
              "Table5": [{
                 "Key1": "Value1",          
                 "Key2": "Value2",          
                 "Key3": "Value3"}]
             }]
       }]    
 }';

所以输入和你一样,那么这里就是递归函数

function toto(array $input, $tableName = '')
{
    foreach ($input as $key => $element) {
        if (is_array($element)) {
            // if key is integer its the first level of array so we keep the $tablename - edited part
            $key = is_int($key) ? $tableName : $key;
            toto($element, $key);
        } else {
            if ($tableName === '') {
                $tableName = 'NonNestedTableName';
            }
            echo "TableName: $tableName, Key: $key, Data: $element \n";
        }
    }
}

$inputArray = json_decode($inputJson, true);

toto($inputArray);

这将显示

表名:NonNestedTableName,键:Key1,数据:Value1

表名:NonNestedTableName,键:Key2,数据:Value2

表名:NonNestedTableName,键:Key3,数据:Value3

表名:Table2,键:Key1,数据:Value1

表名:Table2,键:Key2,数据:Value2

表名:Table2,键:Key3,数据:Value3

表名:Table2,键:Key1,数据:Value1

表名:Table2,键:Key2,数据:Value2

表名:Table2,键:Key3,数据:Value3

表名:Table3,键:Key1,数据:Value1

表名:Table3,键:Key2,数据:Value2

表名:Table3,键:Key3,数据:Value3

表名:Table4,键:Key1,数据:Value1

表名:Table4,键:Key2,数据:Value2

表名:Table4,键:Key3,数据:Value3

表名:Table5,键:Key1,数据:Value1

表名:Table5,键:Key2,数据:Value2

表名:Table5,键:Key3,数据:Value3

【讨论】:

  • so 非常接近...除了,使用您的示例,嵌套数组的表名需要是数组键,即 level1、level11 等,而不是索引号。谢谢!
  • 这有什么问题? key11 和 key12 的 tableName 应该是什么?
  • 好的,不太明白。请准确告诉我您期望 value11、value12 的 tableName 是什么。
  • 需要将表名设置为数组名,而不是索引,所以对于"level1" => [ "key11" => "value11", "key12" => "value12" , 表名将是 "level1", fieldname1="key11", datafield1="value11";字段名 2 =“键 12”,数据字段 2 =“值 12”。在实践中,“level1”可能是“Customer”:[“name”:“john”,“address”:“123 Main Street”] .. 所以这需要转到 Customer 表。
  • 是的,但是如果您查看我的输出,它的 cas TableName: level1, Key: key11, Data: value11 和 value12 的相同 tableName。所以它正是你在previius评论中写的
【解决方案2】:

也许您可以尝试json_decode 将 JSON 字符串转换为数组。它也处理嵌套级别。

试试看:http://php.net/manual/en/function.json-decode.php

【讨论】:

  • 是的,但是一旦你有了阵列,你会怎么做?这就是这个问题的重点!
猜你喜欢
  • 2013-06-08
  • 1970-01-01
  • 2023-01-07
  • 2020-08-29
  • 1970-01-01
  • 1970-01-01
  • 2019-11-13
  • 2020-12-10
  • 1970-01-01
相关资源
最近更新 更多