Right now, if you have a field collection on a node and you export it using D8's REST functionality (either by adding a ?_format=json parameter, or doing a REST export in Views), you get a stub:

"field_fc_project": [{
    "value": "1",
    "revision_id": "1"
}]

We can implement a custom Normalizer to tell Drupal to return the full field collection item, instead of just value and revision_id. Something that looks a little more like...

"field_fc_project": [{
    "item_id": [{
        "value": "1"
    }],
    "host_type": [{
        "value": "node"
    }],
    "uuid": [{
        "value": "24371318-6ab6-4833-ac00-f95df38d46d7"
    }],
    "revision_id": [{
        "value": "1"
    }],
    "field_name": [{
        "target_id": "field_fc_project"
    }],
    "field_some_custom_field": [{
        "value": "This is my string field that I added"
    }]
}]

Comments

charginghawk created an issue. See original summary.

charginghawk’s picture

Status: Active » Needs review
StatusFileSize
new1.67 KB

Here's my patch to accomplish the above, modeled after: https://api.drupal.org/api/drupal/core!modules!serialization!src!Normali...

This doesn't seem to work with HAL output though. That may need an additional normalizer.

tim.plunkett’s picture

Thanks! This could use some test coverage though.

tim.plunkett’s picture

Status: Needs review » Needs work
ashopin’s picture

I tried to apply the patch on the latest Dev version and got the following error when I try 'drush cr':

HP Fatal error:  Class 'Drupal\field_collection\Normalizer\FieldCollectionItemNormalizer' not found in /drupal/core/lib/Drupal/Component/DependencyInjection/Container.php on line 265
Drush command terminated abnormally due to an unrecoverable error.  
Error: Class
'Drupal\field_collection\Normalizer\FieldCollectionItemNormalizer'
not found in
/drupal/core/lib/Drupal/Component/DependencyInjection/Container.php,
line 265
marcel.jtf’s picture

Patch works fine when format = entity. It does not work when format = fields.

jmuzz’s picture

I've looked briefly at the possibility of making tests for this. FieldCollectionBasicTestCase will start getting unwieldy if more tests keep getting added to it, so I created #2760431: Move setup and helper functions out of FieldCollectionBasicTestCase as a soft pre-requisite for making these tests.

  • jmuzz committed 35d1de1 on 8.x-1.x authored by charginghawk
    Issue #2614292 by charginghawk: Added REST/Serialized Output (JSON) of...
  • jmuzz committed d38a3c8 on 8.x-1.x
    Issue #2614292 by jmuzz: Tests for REST/Serialized Output (JSON) of...
jmuzz’s picture

Status: Needs work » Active

Thanks @charginghawk. I'm going to leave this open now as HAL still isn't supported. REST is a big topic. It might be worth making separate issues for the other formats and request types and a meta issue for them.

  • jmuzz committed 35d1de1 on 8.x-3.x authored by charginghawk
    Issue #2614292 by charginghawk: Added REST/Serialized Output (JSON) of...
  • jmuzz committed d38a3c8 on 8.x-3.x
    Issue #2614292 by jmuzz: Tests for REST/Serialized Output (JSON) of...
jmuzz’s picture

Version: 8.x-1.x-dev » 8.x-3.x-dev

Development is moving to 8.x-3.x.

paranojik’s picture

Status: Active » Needs review
StatusFileSize
new4.59 KB

This should take care of HAL support. Co-authored with @das-peter.

Status: Needs review » Needs work

The last submitted patch, 13: 2614292-Added-HAL-serialization-support-13.patch, failed testing.

das-peter’s picture

Hmm, not quite sure how we resolve the dependency to rest.link_manager. I don't think we want to introduce a dependency as it's not required to run the module itself but only if we want to run with HAL.
I think we can add the new HAL normalizer conditionally - just if HAL is enabled. I assume we can do this using code similar to the one in the Default Content module which provides a ServiceProvider:

/**
 * Adds customized normalizer to handle taxonomy hierarchy.
 */
class DefaultContentServiceProvider extends ServiceProviderBase {

  /**
   * {@inheritdoc}
   */
  public function alter(ContainerBuilder $container) {
    $modules = $container->getParameter('container.modules');
    // @todo Get rid of after https://www.drupal.org/node/2543726
    if (isset($modules['taxonomy'])) {
      // Add a normalizer service for term entities.
      $service_definition = new Definition('Drupal\default_content\Normalizer\TermEntityNormalizer', [
        new Reference('rest.link_manager'),
        new Reference('entity.manager'),
        new Reference('module_handler'),
      ]);
      // The priority must be higher than that of
      // serializer.normalizer.entity.hal in hal.services.yml.
      $service_definition->addTag('normalizer', ['priority' => 30]);
      $container->setDefinition('default_content.normalizer.taxonomy_term.halt', $service_definition);
    }
  }

}
paranojik’s picture

Status: Needs work » Needs review
StatusFileSize
new6.43 KB

...there. This should fix the HAL dependency as proposed in #15. @das-peter, thanks for all the assistance!

das-peter’s picture

Woohoo, sweet thanks for the patch.
I like the patch and couldn't find things to nag about - but wont set to RTBC as I'm to closely involved with what was created ;)

alanyong’s picture

What i get is HTML in JSON.
\n\n\n <div class=\"field field--name-field-mall field--type-entity-reference field--label-hidden field--item\">7</div>\n \n <div class=\"field field--name-field-address field--type-string-long field--label-hidden field--item\">20, Level 5</div>\n \n <div class=\"field field--name-field-state field--type-entity-reference field--label-hidden field--item\">Kuala Lumpur</div>\n \n

how to fix this ?

wim leers’s picture

Issue tags: +API-First Initiative
Related issues: +#2824012: Rest-Support

Without this, you can't interact with field collections via REST (or JSON API for that matter).

I had https://www.drupal.org/u/susannecoates send me an e-mail asking about this, but I'm a maintainer of the core REST module, and Drupal core obviously doesn't have field collections :)

Also marked #2824012: Rest-Support as a duplicate of this.

wim leers’s picture

Title: Add REST/Serialized Output (HAL, JSON) of Field Collection Items » Add normalizers for Field Collection Items (to enable REST/JSON API support)
Status: Needs review » Needs work
  1. +++ b/src/Entity/FieldCollectionItem.php
    @@ -133,6 +144,13 @@ class FieldCollectionItem extends ContentEntityBase implements FieldCollectionIt
    +  public function skipHostCheck($bool) {
    +    $this->skip_host_check = $bool;
    +  }
    
    @@ -161,7 +179,8 @@ class FieldCollectionItem extends ContentEntityBase implements FieldCollectionIt
    -    if ($skip_host_save) {
    +    if ($skip_host_save || $this->skip_host_check) {
    +      $this->skip_host_check = FALSE;
    
    +++ b/src/Normalizer/FieldCollectionItemNormalizerHal.php
    @@ -0,0 +1,28 @@
    +  public function denormalize($data, $class, $format = NULL, array $context = array()) {
    +    $entity = parent::denormalize($data, $class, $format, $context);
    +    $entity->skipHostCheck(TRUE);
    +    return $entity;
    +  }
    

    This looks very scary. It also seems to be polluting the public API (but I don't know field_collection well enough to judge this).

  2. +++ b/src/Normalizer/FieldCollectionItemNormalizer.php
    @@ -27,4 +27,13 @@ class FieldCollectionItemNormalizer extends ComplexDataNormalizer {
    +  public function supportsNormalization($data, $format = NULL) {
    +    // Don't use this normalizer for hal_json. FieldCollectionItemNormalizerHal
    +    // will be used instead and just export the references.
    +    return ($format != 'hal_json') && parent::supportsNormalization($data, $format);
    +  }
    +
    

    This can probably be removed entirely by setting the $format property.

FYI: for tests, you can find examples of how to create functional test coverage for a specific field type/normalizer in:

  1. \Drupal\Tests\datetime\Functional\EntityResource\EntityTest\EntityTestDateonlyTest
  2. \Drupal\Tests\datetime\Functional\EntityResource\EntityTest\EntityTestDatetimeTest
cytherion’s picture

Commenting on #19

Thanks Wim.
As my issue is related specifically to field collection items I have opened a new issue here: https://www.drupal.org/node/2893924
-Susanne

mlulu’s picture

I'm facing an issue with posting a field collection item using RESTful API, I used the patch #16 but I'm still getting 403 error access denied

ram4nd’s picture

Status: Needs work » Closed (won't fix)
Issue tags: -Needs tests, -API-First Initiative