This is the integration for double_field module and jsonapi extras which allow to change outputs like

{
  'first': 'A value',
  'second': 123
}

To a more meaningful value like:

{
  'description': 'A box',
  'size': 123
}
CommentFileSizeAuthor
#4 2887372-4.patch3.94 KBdagmar
#2 2887372-2.patch2.54 KBdagmar

Comments

dagmar created an issue. See original summary.

dagmar’s picture

Status: Active » Needs review
StatusFileSize
new2.54 KB
dagmar’s picture

I guess my question is how can I get the schema from the field so I only have to change the keys of the array.

+    return [
+      "type" => "object",
+      "properties" => [
+        $settings['first'] => [
+          "type" => "boolean",  // this should be dynamic
+          "title" => "Boolean"    // this should be dynamic
+        ],
+        $settings['second'] => [
+          "type" => "string",    // this should be dynamic
+          "title" => "Text"         // this should be dynamic
+        ]
+      ]
+    ];
dagmar’s picture

Project: JSON:API Extras » Double Field
Version: 8.x-1.x-dev » 8.x-3.x-dev
Issue summary: View changes
StatusFileSize
new3.94 KB

Oh, I think I found the way. Here is the new patch.

dagmar’s picture

Issue summary: View changes
chi’s picture

I would like someone with JSON API experience make a review.

wim leers’s picture

Title: Support jsonapi_extras in double_field » Add normalizer for Double Field, for better normalization in core REST & JSON API
Issue tags: +API-First Initiative

I am … very confused by this code :D

This patch is achieving "better keys" by subclassing ResourceFieldEnhancerBase, which is a JSON API extras addition. But JSON API Extras designed to override things.

Why not fix the root cause? You can do that by writing a normalizer (see https://www.drupal.org/docs/8/api/serialization-api/serialization-api-ov...). Then it would work in core REST, and in JSON API — even without installing JSON API Extras! See \Drupal\serialization\Normalizer\TimestampItemNormalizer and \Drupal\serialization\Normalizer\EntityReferenceFieldItemNormalizer for examples. More of these field type-specific normalizers are being worked on, and will be landing in the coming days, weeks and months in Drupal core :)

dagmar’s picture

@Wim Leers. That's a great idea! The only problem I see here is where to define those mappings. Double field currently doesn't have a place to do that. That's the reason ResourceFieldEnhancer seemed a good alternative.

@Chi, Do you think we can add an extra pair of settings to define identifiers for 'first' and 'second' replacements for double fields. Or maybe you already know a some settings we could use for this task.

wim leers’s picture

Oh… well you could add new optional settings to Double Field?

chi’s picture

Can this be done by setting supportedInterfaceOrClass property of the normalizer?

wim leers’s picture

Yes.

chi’s picture

The approach with normalizer seems super simple.

double_field.services.yml

services:
  serializer.normalizer.double_field:
    class: Drupal\double_field\Normalizer\DoubleFieldItemNormalizer
    tags:
      - { name: normalizer, priority: 10 }


src/Normalizer/DoubleFieldItemNormalizer.php


namespace Drupal\double_field\Normalizer;

use Drupal\double_field\Plugin\Field\FieldType\DoubleField;
use Drupal\serialization\Normalizer\NormalizerBase;

/**
 * Converts values for DoubleFieldItem.
 */
class DoubleFieldItemNormalizer extends NormalizerBase {

  /**
   * {@inheritdoc}
   */
  protected $supportedInterfaceOrClass = DoubleField::class;

  /**
   * {@inheritdoc}
   */
  public function normalize($field, $format = NULL, array $context = array()) {
    $value = $field->getValue();
    return [
      'description' => $value['first'],
      'size' => $value['second'],
    ];
  }

}

chi’s picture

Unfortunately normalizers are not configurable and Double field has no appropriate settings to make use. Introducing additional configuration to field instance for such a specific case as renaming properties in JSON output does not seem a good idea.

dagmar’s picture

Introducing additional configuration to field instance for such a specific case as renaming properties in JSON output does not seem a good idea.

Well, that's the main reason why this lives into a jsonapi_extra plugin. The plugin offers the configurations to store those values.

dagmar’s picture

I created this issue that is related #2892193: Custom normalizers are not respected

e0ipso’s picture

Project: Double Field » JSON:API Extras
Version: 8.x-3.x-dev » 8.x-1.x-dev

This could probably be a Field Enhancer in JSON API extras.

wim leers’s picture

Title: Add normalizer for Double Field, for better normalization in core REST & JSON API » Add "subfield name" to storage settings for Double Field, for better normalization in core REST, JSON API and GraphQL
Project: JSON:API Extras » Double Field
Version: 8.x-1.x-dev » 8.x-3.x-dev

Introducing additional configuration to field instance for such a specific case as renaming properties in JSON output does not seem a good idea.

But if it's implemented at the normalizer level, then that will only work in the JSON API module (or only in the REST module), but it will not work in https://www.drupal.org/project/graphql nor in https://www.drupal.org/project/openapi.

Ideally, DoubleField::propertyDefinitions() would not use first and second as property names, but it'd use configurable, named properties. That's only possible if those property names were defined in the accompanying field storage definition (FieldStorageDefinitionInterface).

If it's possible to store a "subfield type" in the field storage definition, then surely it's also possible to store a name for them? Then

    foreach (['first', 'second'] as $subfield) {
      $subfield_type = $settings['storage'][$subfield]['type'];
…
      $properties[$subfield] = …

could be modified to

    foreach (['first', 'second'] as $subfield) {
      $subfield_type = $settings['storage'][$subfield]['type'];
…
      $subfield_name = $settings['storage'][$subfield]['name'];
      $properties[$subfield_name] = …     

(And for BC, you can generate the defaults to be first and second, so that existing Double Fields continue to work as they do today.)

That would then make Double Field compatible with all API-First modules.

chi’s picture

Version: 8.x-3.x-dev » 4.x-dev
Status: Needs review » Closed (won't fix)

Anyone who has time to implement this as described in #17 feel free to reopen the issue.