1

I have a model field ("data") which maps to a json MYSQL field as follows:

class Person {

    /** @Id @Column(type="integer", name="person_id") @GeneratedValue **/
    protected $id;

    /** @Column(type="json") **/
    protected $data;

    /** @Column(type="string") **/
    protected $name;

}

I am able to query and serialize Person, but the data fields are nested:

$person = $personRepository->find(11);
echo $serializer->serialize($person, 'json');
//returns {"id": 11, "name": "Daniel", "data": {"age": 57, "city": "Omaha"} }

I would like to un-nest the data field so that it serializes inline.

//returns {"id": 11, "name": "Daniel", "age": 57, "city": "Omaha"}

Is this possible?

1
  • You can try with writing a custom normalizer for this entity type that just merges the 'data' key value array into the main array and removes the 'data' key... Or if you need to also de-serialize the data back into an entity later on, you can check out the custom encoder. I haven't used/needed these in practice but in theory those look to provide an answer to your question :) Commented Oct 2, 2019 at 6:07

1 Answer 1

1

I see different solutions here, ranging from awfully dirty to "well, that's okay"

all solutions that are not awfully dirty (like string replacing braces and stuff), all work on the normalized array:

$array = $serializer->normalize($person);
/** add code, that turns $array into flattened version $flattened */
$json = $serializer->encode($flattened, 'json');

now, what is that code that flattens the array ... for example this:

// if this is done in a loop, this, $flattened should be reinitialized every iteration!!!
$flattened = []; 
array_walk_recursive($array, function($value, $key) use (&$flattened) {
    $target[$key] = $value;
});
// $flattened contains the flattened array

a slightly longer version though:

// define somewhere outside of loop
function flatten($array, $flattened = []) {
    foreach($array as $key => $value) {
        if(is_array($value)) {
            $flattened = flatten($value, $flattened);
        } else {
            $flattened[$key] = $value;
        }
    }
    return $flattened;
}

// call flatten
$flattened = flatten($array);

the very fancy solution would be, to integrate all of this in your custom encoder, that extends the json encoder, but I guess that's already overkill.

also please note, that this can and will break in sooo many cases, because keys can be overridden, it cannot be applied to arrays of objects without iterating over them, it will produce probably unwanted result for nested objects, etc.

Sign up to request clarification or add additional context in comments.

Comments

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.