nilportugues / symfony-jsonapi

JSON API Transformer Bundle for Symfony 2 and Symfony 3
http://nilportugues.com
MIT License
115 stars 19 forks source link

How to avoid serializing compound objects? #20

Closed franbenz closed 8 years ago

franbenz commented 8 years ago

Hi Nil. Is there a way to avoid using the top-level included member? Here is an example: 1) The entity Invoice has a many to one relation to Customer; 2) The entity Invoice_detail has a many to one relation to an Invoice; If I'm forced to use the included member, to avoid the doctrine closure issue, then every time I request an Invoice_detail to the jsonapi I would have to include in the request the Invoice and the Customer. Is this approach the right way to use the API?

franbenz commented 8 years ago

Anyone else with the same issue?

nilportugues commented 8 years ago

@franbenz map it as a plain array.

But the standard uses included for a reason.

franbenz commented 8 years ago

Thanks. Is there a doc about mappings? About the standard, the spec mentions the optional use of Compound Documents "To reduce the number of HTTP requests". But I don't think I should use a Compound Document for every request of Invoice_detail entities.

nilportugues commented 8 years ago

@franbenz A doc about mappings for this library you mean?

franbenz commented 8 years ago

@nilportugues Yes, I can't find how to map a doctrine entity to a plain array in the yml mappings from this library.

nilportugues commented 8 years ago

There's no need to map arrays, the serializer will pick them up

franbenz commented 8 years ago

@nilportugues Hi Nil. When I use doctrine's HIDRATE_ARRAY and pass the result to the serializer, I get Notice: Undefined index: @type. Is there another way for the serializer to pick up the array as you suggested above?

Serialization:

$query = $manager->createQuery("SELECT o, c FROM AppBundle:Obras o
                    left join o.cliente c
                    where o.id = :idObra")->setParameter('idObra',$obra->getId());
$newObra = $query->getResult(Query::HYDRATE_ARRAY);
$jsonApiSerializer = $this->get('nil_portugues.serializer.json_api_serializer');
$serializedObject = $jsonApiSerializer->serialize($newObra);// Undefined index: @type

The $newObra array from doctrine looks like this:

*array* _(size=1)_
  0 => 
    *array* _(size=4)_
      'id' => int 68
      'nombre' => string '1234567890' _(length=10)_
      'activo' => boolean true
      'cliente' => 
        *array* _(size=3)_
          'id' => int 1
          'nombre' => string 'CLIENTE' _(length=7)_
          'activo' => boolean true
nilportugues commented 8 years ago

Mind updating to 1.4.0? I've applied some changes to the underlying lib that should fix this.

franbenz commented 8 years ago

Hi @nilportugues . After the update to 1.4.0. the json-api package was updated. But I'm still getting "Undefined index: @type" when serializing the array generated by doctrine.

nilportugues commented 8 years ago

@franbenz thanks for the patience. Try this.

As it has @type... so it's definately an ArrayCollection from Doctrine, and not an array.

Write a mapper for it and let me know if it solves the problem.

franbenz commented 8 years ago

The array I'm getting from Doctrine is not really an ArrayCollection, please look the var_dump from my previous comment. It does not include any class or type information. This is a portion of the callstack:

1.  in vendor\nilportugues\json-api\src\Helpers\PropertyHelper.php at line 31 
2.  at ErrorHandler ->handleError ('8', 'Undefined index: @type', 'C:\xampp\htdocs\tapeApi\vendor\nilportugues\json-api\src\Helpers\PropertyHelper.php', '31', 
array('mappings' => array('AppBundle\Entity\Clientes' => object(Mapping), 'AppBundle\Entity\Items_Presupuesto' => object(Mapping), 'AppBundle\Entity\Obras' => object(Mapping), 'AppBundle\Entity\Presupuestos' => object(Mapping), 'AppBundle\Entity\User' => object(Mapping)), 
'value' => array('@map' => 'array', '@value' => array('id' => array('@scalar' => 'integer', '@value' => '94'), 'nombre' => array('@scalar' => 'string', '@value' => 'Obra de pruebaaa22'), 'activo' => array('@scalar' => 'boolean', '@value' => true), 'cliente' => array('@map' => 'array', '@value' => array('id' => array('@scalar' => 'integer', '@value' => '1'), 'nombre' => array('@scalar' => 'string', '@value' => 'CLIENTE'), 'activo' => array('@scalar' => 'boolean', '@value' => true))))))) 
in vendor\nilportugues\json-api\src\Helpers\PropertyHelper.php at line 31 
3. at PropertyHelper ::setResponseDataTypeAndId (
array('AppBundle\Entity\Clientes' => object(Mapping), 'AppBundle\Entity\Items_Presupuesto' => object(Mapping), 'AppBundle\Entity\Obras' => object(Mapping), 'AppBundle\Entity\Presupuestos' => object(Mapping), 'AppBundle\Entity\User' => object(Mapping)), 
array('@map' => 'array', '@value' => array('id' => array('@scalar' => 'integer', '@value' => '94'), 'nombre' => array('@scalar' => 'string', '@value' => 'Obra de pruebaaa22'), 'activo' => array('@scalar' => 'boolean', '@value' => true), 'cliente' => array('@map' => 'array', '@value' => array('id' => array('@scalar' => 'integer', '@value' => '1'), 'nombre' => array('@scalar' => 'string', '@value' => 'CLIENTE'), 'activo' => array('@scalar' => 'boolean', '@value' => true)))))) 
in vendor\nilportugues\json-api\src\JsonApiTransformer.php at line 97
nilportugues commented 8 years ago

@franbenz I can fix it. Give me second.

nilportugues commented 8 years ago

@franbenz fetch new version with composer update nilportugues/json-api (Updates underlying library causing the error)

franbenz commented 8 years ago

The undefined index notice is still occurring(empty function must receive a variable and not an expression). We've corrected it here, but now it happens in setResponseDataAttributes in vendor\nilportugues\json-api\src\Helpers\DataAttributesHelper.php at line 100. We don't know what should this function do when there is no type.

nilportugues commented 8 years ago

Mind sharing the object structure? Nestings, etc etc?

The code should not take you to DataAttributesHelper line 100 if it's not an object.

franbenz commented 8 years ago

This is what the builtin serialize function from php returns for the array I'm passing to the serialize function from the json-api library. It's just an array:

string 'a:1:{i:0;a:4:{s:2:"id";i:100;s:6:"nombre";s:18:"Obra de pruebaaa22";s:6:"activo";b:1;s:7:"cliente";a:3:{s:2:"id";i:1;s:6:"nombre";s:7:"CLIENTE";s:6:"activo";b:1;}}}' (length=164)

This array was obtained from $array = $query->getResult(Query::HYDRATE_ARRAY);

nilportugues commented 8 years ago

@franbenz did you find a solution for these or I need to look into it?

franbenz commented 8 years ago

For now we've stopped using these arrays serializations, though probably still a bug. There's just no hurry right now. Thanks Nil!