Change record status: 
Project: 
Introduced in branch: 
8.3.x
Introduced in version: 
8.3.0
Description: 

Before

In Drupal 8.0, 8.1 and 8.2, all serialized values in the JSON, HAL+JSON and other formats are strings. Even integers and booleans. In other words, when requesting an article in JSON format, you'd get something like:

{
  title: 'this is a string and it makes sense',
  published: '1',
  rating: '7',
  sticky: '0'
}
  1. title is a string and it makes sense
  2. published is a boolean "true" but it's serialized to '1' instead of true
  3. rating is a rating from 1 to 10, but it's serialized to '7' instead of 7
  4. sticky is a boolean "false" but it's serialized to '0' instead of false

This is undesirable developer experience for consumers of serialized data (for example, decoupled applications) and requires additional conversions.

After

In Drupal 8.3, booleans are serialized to booleans, and integers are serialized to integers:

{
  title: 'this is a string and it makes sense',
  published: true,
  rating: 7,
  sticky: false
}

Backwards compatible: existing sites can opt in to the old behavior

All sites, including existing sites get the new behavior by default, which means they may have backwards-compatibility breaks if they expect all data types to be returned as strings.

Sites can opt in to keep the old behavior by changing the bc_primitives_as_strings key's value from false to true in serialization.settings configuration using one of the following mechanisms:

  1. Use the Configuration API in custom module or integration code.
  2. Use Drush: drush config-set serialization.settings bc_primitives_as_strings TRUE
  3. Use configuration override

This backwards compatibility layer will be maintained until Drupal 9; in Drupal 9.0 it will be dropped.

Workarounds for individual applications

In some cases, a site may still require string values for a certain serialization format, when the parent site has not enabled the BC layer. This may occur if you have two decoupled clients using different serialization formats. One of the clients may handle the new behavior correctly while the other may not. In this case a site may cast values to strings for one serialization format only as a hotfix until the client is updated to handle the proper data types.

Below is an example of how you could accomplish this in a module to provide a temporary workaround if the site needed the 'json' format only use string values:

In example.services.yml

  # Override the PrimitiveDataNormalizer to allow uncasted values for select formats.
  serializer.normalizer.primitive_data.uncasted:
    class: Drupal\example\Normalizer\UncastedPrimitiveDataNormalizer
    # The PrimitiveDataNormalizer uses priority 5.
    tags:
      - { name: normalizer, priority: 10 }

example/src/Normalizer/UncastedPrimitiveDataNormalize.php


namespace Drupal\example\Normalizer;

use Drupal\serialization\Normalizer\PrimitiveDataNormalizer;

/**
 * Overrides the PrimitiveDataNormalizer to use the uncasted (string) values.
 *
 * This change means values will be retrieved as strings, matching the behavior
 * of the JSON output before the PrimitiveDataNormalizer was added to
 * the system in Drupal 8.3.
 */
class UncastedPrimitiveDataNormalizer extends PrimitiveDataNormalizer {

  /**
   * {@inheritdoc}
   */
  protected $format = ['json'];

  /**
   * {@inheritdoc}
   */
  public function normalize($object, $format = NULL, array $context = array()) {
    return $object->getValue();
  }

}
Impacts: 
Module developers
Themers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done