在Laravel中,我执行了一个JSON映射,其中我需要将JSON转换为不同的模式.为此,我遵循以下步骤:

  1. 用Arr::dot helper点array.这样我就得到了这个结果,例如:
array(11) {
  ["0.identificador"]=>
  int(1)
  ["0.nome_completo"]=>
  string(8) "John Doe"
  ["0.email"]=>
  string(11) "j@email.com"
  ["0.empresa.razao_social"]=>
  string(11) "ABC Company"
  ["0.empresa.endereco"]=>
  string(11) "123 Main St"
  ["0.pedidos.0.SKU"]=>
  int(1)
  ["0.pedidos.0.descricao"]=>
  string(5) "Shoes"
  ["0.pedidos.0.qtd"]=>
  int(2)
  ["0.pedidos.1.SKU"]=>
  int(2)
  ["0.pedidos.1.descricao"]=>
  string(5) "Shirt"
  ["0.pedidos.1.qtd"]=>
  int(1)
}
  1. 迭代通过点数组,并与我的键映射进行比较.如果它们匹配,我用映射键设置值.

我的映射看起来像这样:

array(8) {
    ["*.identificador"]=> string(4) "*.id"
    ["*.nome_completo"]=> string(6) "*.name"
    ["*.empresa"]=> string(9) "*.company"
    ["*.empresa.razao_social"]=> string(14) "*.company.name"
    ["*.empresa.endereco"]=> string(17) "*.company.address"
    ["*.pedidos.*.SKU"]=> string(13) "*.orders.*.id"
    ["*.pedidos.*.descricao"]=> string(18) "*.orders.*.product"
    ["*.pedidos.*.qtd"]=> string(19) "*.orders.*.quantity"
  }

这就是我的代码到目前为止的样子:


$payload = [
    [
        "identificador" => 1,
        "nome_completo" => "John Doe",
        "email" => "j@email.com",
        "empresa" => [
            "razao_social" => "ABC Company",
            "endereco" => "123 Main St"
        ],
        "pedidos" => [
            [
                "SKU" => 1,
                "descricao" => "Shoes",
                "qtd" => 2
            ],
            [
                "SKU" => 2,
                "descricao" => "Shirt",
                "qtd" => 1
            ]
        ]
    ]
];

$dottedPayload = Arr::dot($payload);

$transformedPayload = [];
foreach ($dottedPayload as $key => $value) {
    $newKey = preg_replace('/\d+./', '*.', $key);
    $newKey = preg_replace('/\.\d+\./', '.*.', $newKey);
    $newKey = preg_replace('/\.\d+$/', '.*', $newKey);

    $mappedKey = $mappingConfig[$newKey] ?? $key;

    data_fill($transformedPayload, $mappedKey, $value);
}

我的输出是这样的:

array(2) {
  ["*"]=>
  array(4) {
    ["id"]=>
    int(1)
    ["name"]=>
    string(8) "John Doe"
    ["company"]=>
    array(2) {
      ["name"]=>
      string(11) "ABC Company"
      ["address"]=>
      string(11) "123 Main St"
    }
    ["orders"]=>
    array(1) {
      ["*"]=>
      array(3) {
        ["id"]=>
        int(2)
        ["product"]=>
        string(5) "Shirt"
        ["quantity"]=>
        int(1)
      }
    }
  }
  [0]=>
  array(1) {
    ["email"]=>
    string(11) "j@email.com"
  }
}

但这是预期的:

$expectedResult = [
    [
        "id" => 1,
        "name" => "John Doe",
        "email" => "j@email.com",
        "company" => [
            "name" => "ABC Company",
            "address" => "123 Main St"
        ],
        "orders" => [
            [
                "id" => 1,
                "product" => "Shoes",
                "quantity" => 2
            ],
            [
                "id" => 2,
                "product" => "Shirt",
                "quantity" => 1
            ]
        ]
    ]
];

如何在映射后正确取消数组的点,使用通配符,正确设置索引?任何其他建议来执行这个JSON映射也是受欢迎的.

推荐答案

由于您希望密钥名的映射是用户可配置的,您可以修改您原来的方法来使用捕获组,这些方法保留由Arr::dot函数插入的数字计数器.

$payload = [
    [
        "identificador" => 1,
        "nome_completo" => "John Doe",
        "email" => "j@email.com",
        "empresa" => [
            "razao_social" => "ABC Company",
            "endereco" => "123 Main St"
        ],
        "pedidos" => [
            [
                "SKU" => 1,
                "descricao" => "Shoes",
                "qtd" => 2
            ],
            [
                "SKU" => 2,
                "descricao" => "Shirt",
                "qtd" => 1
            ]
        ]
    ]
];

$regexMapping = [
  'identificador' => 'id',
  'nome_completo' => 'name',
  'email' => 'email',
  'empresa\.razao_social' => 'company.name',
  'empresa\.endereco' => 'company.address',
  'pedidos\.(\d+)\.SKU' => 'orders.$1.id',
  'pedidos\.(\d+)\.descricao' => 'orders.$1.product',
  'pedidos\.(\d+)\.qtd' => 'orders.$1.quantity',
];

$dotted = Arr::dot($payload);
$newPayload = [];
$replacements = 0;

foreach ($dotted as $key => $value) {
  foreach ($regexMapping as $pattern => $replacement) {
    $newKey = preg_replace('/'.$pattern.'/', $replacement, $key, -1, $replacements);
    if ($replacements) {
      // only store the new key if we replaced something
      $newPayload[$newKey] = $value;
      // match found, no need to check any more patterns
      break; 
    }
  }
}

Arr::undot($newPayload);

结果是:

[
  [
    "id" => 1,
    "name" => "John Doe",
    "email" => "j@email.com",
    "company" => [
      "name" => "ABC Company",
      "address" => "123 Main St",
    ],
    "orders" => [
      [
        "id" => 1,
        "product" => "Shoes",
        "quantity" => 2,
      ],
      [
        "id" => 2,
        "product" => "Shirt",
        "quantity" => 1,
      ],
    ],
  ],
]

这种方法的低效之处在于嵌套循环;但是为了理解它是如何工作的,并且如果您只有几个映射,这不是一个大问题.

Php相关问答推荐

无法添加ProxyClass__setInitialized()上的忽略

未在moodle上运行的计划任务

如果再次调用SESSION_START(),会话.gc-max是否会重新启动?或者它是从第一次创建会话开始计算的?

保存PHP条带以备将来使用,不显示用户界面

将部分产品排除在WooCommerce的计算附加费之外

在WooCommerce管理中 for each 运输方法设置添加自定义字段

PHP文件上载问题-";Move_Uploaded_Files";未按预期工作

PHP Match如何准确判断条件?

在WooCommerce购物车页面应用优惠券不会';t刷新总计

关于Laravel缓存出现的错误

在 Woocommerce 邮箱订单中显示产品 GTIN

WooCommerce:如果购物车中已存在产品,则增加购物车商品数量

PHP 中使用 JSON 的自定义会话处理程序会因错误而 destruct 会话

使用 foreach php 将记录正确分配给正确的父级

在WooCommerce购物车和 checkout 页面中更改总计文本

在PHP WordPress插件中使用变量连接路径时的问题解决方法

Shopware 6.4.20店铺激活问题

PHP 中的 curl 验证失败(openssh 连接正常)

使用 v-for 的存储链接中的 Img src 在 Laravel vuejs 中不起作用

Laravel 自定义中间件:ERR_TOO_MANY_REDIRECTS