1

I have a JSON object that I try to modify. So I created the following function. I firstly deserialize the JSON object and then given the array and the path that I want to change I modify the value.

function setInDict($arr, $path, $value){
    switch(sizeof($path)){
        case 1:
            $arr[$path[0]] = $value;
            break;
        case 2:
            $arr[$path[0]][$path[1]] = $value;
            break;
        case 3:
            $arr[$path[0]][$path[1]][$path[2]] = $value;
            break;      
        case 4:
            $arr[$path[0]][$path[1]][$path[2]][$path[3]] = $value;
            break;
        case 5:
            $arr[$path[0]][$path[1]][$path[2]][$path[3]][$path[4]] = $value;
            break;
    }
    return $arr;
}

I tried a lot of things(recursion, &arr) to make it work dynamically but my PHP experience is limited and I cant make it to work.

Is there a clean way to do this. Is there something alternative that I can try?

For example I have the following JSON and I want to modify subsubkey to value 2

{  
  "key":{  
    "subkey":{  
      "subsubkey":3
    }
  }
}

I deserialize it using json_decode($json, true); and I create the $path array which would be

['key', 'subkey', 'subsubkey']
3

2 Answers 2

1

If you don't want to create new updated array recursively you can use references. The following code walks through the given array and on each iteration changes the reference to the nested array until it reaches the field you want to change.

function setInDict(array $array, array $path, $value)
{
    if (!$path) {
        return $array;
    }

    $found = &$array;
    foreach ($path as $field) {
        if (!isset($found[$field]) || !array_key_exists($field, $found)) {
            throw new \InvalidArgumentException("There is no nested field '$field' in the given array");
        }

        $found = &$found[$field];
    }

    $found = $value;

    return $array;
}
Sign up to request clarification or add additional context in comments.

4 Comments

That's what I was trying to express but I think I have misused references.
Can I also delete the key found using this?
Yes, but the code will be a little bit different. You have to unset the last key from the path.
Should be something like this if ($isLast) unset($found[$field]); else $found = &$found[$field];
1

Is this what you are looking for?

$x= '{  
  "key":{  
    "subkey":{  
      "subsubkey":3
    },
    "subkeyx":{  
      "subsuwefwef":3
    }
  }
}';

$x = json_decode($x, true);
echo json_encode(checkValue($x,2,"subsubkey"));

function checkValue($x,$y,$keyName){

    if(is_array($x)){
        foreach($x as $key=>$value){
            if(is_array($value)){
                $check = checkValue($value,$y,$keyName);
                $x[$key] = $check;
            }elseif($key == $keyName){
                $x[$key] = $y;

            } 

        }
    }

    return $x;

}

Output:

{"key":{"subkey":{"subsubkey":2},"subkeyx":{"subsuwefwef":3}}}

3 Comments

This will change all keys recursively and not the specified one in the $path.
@YoloQ I edited so it will check for "subsubkey". will that work for you? it won't check the whole path. just the last key in the path.
See the accepted answer of what I was trying to accomplish.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.