这是我正在使用的php_decoded JSON结构的一个exerpt:
array(3) {
["$type"]=> string(51) "NanoWebInterpreter.WebInputData, NanoWebInterpreter"
["NBBList"]=>
array(2) {
["$type"]=> string(81) "System.Collections.Generic.List`1[[monoTNP.Common.NBB, monoTNP.Common]], mscorlib"
["$values"]=>
array(1) {
[0]=>
array(6) {
["$type"]=> string(34) "monoTNP.Common.NBB, monoTNP.Common"
["ID"]=> string(16) "id-0065-00000003"
["MPList"]=>
array(2) {
["$type"]=> string(80) "System.Collections.Generic.List`1[[monoTNP.Common.MP, monoTNP.Common]], mscorlib"
["$values"]=>
array(3) {
[0]=>
array(9) {
["$type"]=> string(43) "monoTNP.Common.EllipticalMP, monoTNP.Common"
["Eccentricity"]=> float(1)
["ID"]=> string(16) "id-0065-00000006"
["ParticleIndex"]=> int(-1)
["DispersionInteractionStrength"]=> float(0)
["DispersionInteractionRange"]=> float(2.5)
["CharacteristicSize"]=> float(0)
["CenterOfMass"]=> string(7) "<0,0,0>"
["OrientationVector"]=> string(2) "<>"
}
我一直在尝试编写这个递归跟踪JSON对象并用$ postvalue替换目标值的函数,但每当我尝试递归执行此操作时,该值不会更改。到目前为止,这是我的代码:
function replaceVal(&$json, $postkey, $postvalue, &$idCounter, $level)
{
$depth = 3;
#Base Case
#At the right depth level, check to see if the idCounter is equal to the
#postkey value (the HTML input field name). If it is, take the
#corresponding key and assign the postvalue to it (the input from form).
#Then return. Otherwise, incrememnt the idCounter and return.
if ($level >= $depth){
foreach($json as $key => $value){
if($idCounter == $postkey){
print "$key => $value\n";
$json[$key] = $postvalue; #Not working properly
return;
}
$idCounter++;
}
}
#Descend down into the level of the tree specified by $depth.
#This level should correspond do the level at which the HTML input
#fields lie
#$idCounter will only be greater than $postkey if the value has
#been changed by the previous if statement. In that case, the job is done
#and the function will terminate.
if ($level < $depth){
foreach($json as $key => $value){
if ($idCounter < $postkey)
replaceVal($value, $postkey, $postvalue, $idCounter, $level+1);
else
return;
}
}
}
有趣的是,如果我直接索引到这样的结构:
$key = &$json['NBBList']['$values'][0]['MPList']['$values'][0]['Eccentricity']
$key = "asdf";
可以更改值。唯一似乎是问题的是递归。这听起来像一个非常容易解决的问题,但我只是编程了不到一年,所以我可能只是错过了一些明显的东西。 &GT;&GT;
哦,postvalue和postkey值来自HTML表单提交。
- edit-- print语句就在那里进行调试。它可以被忽略。
编辑2: 以下是函数的调用方式:
foreach ($_POST as $postkey => $postvalue)
{
if ($postvalue != ""){
print "$postkey => $postvalue\n";
$idCounter = 1;
replaceVal($json['NBBList']['$values'][0], $postkey, $postvalue, $idCounter, 0);
}
}
同样,print语句用于调试目的。 附加信息:HTML输入字段的名称是根据它们在JSON树中的顺序动态分配的数字。因此,递增变量idCounter对应于前进到下一个输入字段 Edit3:在评论中添加了代码。
答案 0 :(得分:1)
你可以(而且应该)总是使用PHP的内部函数,万一有。
如果您不需要计数器,可以查看array_replace_recursive。在这种情况下,您的代码将如下所示:
function replaceVal(&$array, $key, $value) {
$array = array_replace_recursive( $array, array( $key => $value ) );
}
修改强>
目前的评论之后:
function replaceVal(&$json, $postkey, $postvalue, &$idCounter, $level)
{
$depth = 3;
if ($level >= $depth){
foreach($json as $key => $value) {
if($idCounter == $postkey) {
$json[$key] = $postvalue; #Not working properly
return;
}
$idCounter++;
}
}
if ($level < $depth){
foreach($json as $key => $value){
if ($idCounter < $postkey)
replaceVal($json[$key], $postkey, $postvalue, $idCounter, $level+1);
else
return;
}
}
}
问题在于,在递归中,您使用$value
的位置是数组元素的副本。然后,编辑了,但更改没有传播到$json
。
答案 1 :(得分:0)
还有另一种方法可以做到这一点。主要思想是将JSON视为字符串,然后使用str_replace或preg_replace(str_replace用于regexp)。有一个例子:
# Creating a mapping array ("old_key_name" => "new_key_name").
# There I'm reading a mapping from the json file $mapping_json_file.
# But you can set your mapping array directly instead, like $mapping_array = array("old_key_name" => "new_key_name",...).
$mapping_array = json_decode(file_get_contents($mapping_json_file),true);
# Replace string
$new_json = str_replace(array_keys($mapping_array ), array_values($mapping_array), $old_json);
注意:最好使用完全匹配来替换字符串。有一种方法可以做到。
# For each key name, replace each $old_key_name by "/\b".$old_key_name."\b/u".
# It's needed for recognizing breakers.
$tmp_arr = array_map(function($k){ return '/\b'.$k.'\b/u'; }, array_keys($mapping_array));
# Now we use "/\b".$old_key_name."\b/u" instead $old_key_name.
$new_json = preg_replace($tmp_arr, array_values($mapping_array), $old_json);