src/Normalizer/FieldItemNormalizer.php
public function normalize($field_item, $format = NULL, array $context = []) {

    // @TODO Understand Drupal complex fields to RDF mapping
    // Fields can be complex, with multiple subfields
    // but i'm not sure if rdf module
    // is able to assign that, so investigate:
    $values = $field_item->toArray();
    // For now we will just pass @value and @language to json-ld
    // Until we find a way of mapping to rdf subfields.
    $values_clean = [];
    $normalized = [];
    $field = $field_item->getParent();

    if (!isset($values['value']) && !isset($values['uri'])) {
      // Makes little sense to add to json-ld without a value or uri.
      return [];
    }
    else {
      // Set the uri here, and then convert it to '@id' later on.
      $values_clean['@value'] = isset($values['value']) ? $values['value'] : $values['uri'];
      if (isset($context['current_entity_rdf_mapping'])) {
        // So why i am passing the whole rdf mapping object and not
        // only the predicate? Well because i hope i will be able
        // to MAP to RDF also sub fields of a complex field someday
        // and somehow.
        $field_mappings = $context['current_entity_rdf_mapping']->getPreparedFieldMapping($field->getName());
        $field_keys = isset($field_mappings['properties']) ? $field_mappings['properties'] : [$field->getName()];

        if (!empty($field_mappings['datatype'])) {
          $values_clean['@type'] = $field_mappings['datatype'];
        }

        // Well, this is json-ld but $field_item->toArray() depends on
        // each field implementation and some don't have 'value key'
        // Maybe i should handle them as _blank nodes?
        // For now this is a dirty solution.
        if (!empty($field_mappings['datatype_callback'])) {
          $callback = $field_mappings['datatype_callback']['callable'];
          $arguments = isset($field_mappings['datatype_callback']['arguments']) ? $field_mappings['datatype_callback']['arguments'] : NULL;
          $values_clean['@value'] = call_user_func($callback, $values, $arguments);
        }
        $field_context = $this->jsonldContextgenerator->getFieldsRdf(
          $context['current_entity_rdf_mapping'],
          $field->getName(),
          $field->getFieldDefinition(),
          $context['namespaces']
        );

        if (isset($field_context[$field_keys[0]])) {
          $values_clean = $values_clean + $field_context[$field_keys[0]];
        }

      }
      else {
        $field_keys = [$field->getName()];
      }

      // JSON-LD Spec says you can't have an @language for a typed values.
      if (isset($context['langcode']) &&
      (!isset($values_clean['@type']) ||
      empty($values_clean['@type']) ||
      $values_clean['@type'] == "xsd:string" ||
      $values_clean['@type'] == "http://www.w3.org/2001/XMLSchema#string")) {
        // @see https://json-ld.org/spec/latest/json-ld/#dfn-strings.
        // Getting rid of @type to allow @language.
        // @see https://json-ld.org/spec/latest/json-ld/#string-internationalization.
        unset($values_clean['@type']);
        $values_clean['@language'] = $context['langcode'];
      }

      array_filter($values_clean);

      // Convert @value to @id if the item we're normalizing is a Link.
      if (isset($values['uri'])) {
        $values_clean['@id'] = $values_clean['@value'];
        unset($values_clean['@value']);
        unset($values_clean['@type']);
      }

      // The values are wrapped in an array, and then wrapped in another array
      // keyed by field name so that field items can be merged by the
      // FieldNormalizer.
      foreach ($field_keys as $field_name) {
        // If there's no context, we need full predicates, not shortened ones.
        if (!$context['needs_jsonldcontext']) {
          $field_name = $this->escapePrefix($field_name, $context['namespaces']);
          foreach ($values_clean as $key => $val) {
            // Expand values in the array, ie. @type values xsd:string.
            $values_clean[$key] = $this->escapePrefix($val, $context['namespaces']);
          }
        }
        $normalized[$field_name] = [$values_clean];
      }
      return $normalized;
    }
  }
public function normalize($field_item, $format = NULL, array $context = []) {

    // @TODO Understand Drupal complex fields to RDF mapping
    // Fields can be complex, with multiple subfields
    // but i'm not sure if rdf module
    // is able to assign that, so investigate:
    $values = $field_item->toArray();
    // For now we will just pass @value and @language to json-ld
    // Until we find a way of mapping to rdf subfields.
    $values_clean = [];
    $normalized = [];
    $field = $field_item->getParent();

    if (!isset($values['value']) && !isset($values['uri'])) {
      // Makes little sense to add to json-ld without a value or uri.
      return [];
    }
    else {
      // Set the uri here, and then convert it to '@id' later on.
      $values_clean['@value'] = isset($values['value']) ? $values['value'] : $values['uri'];
      if (isset($context['current_entity_rdf_mapping'])) {
        // So why i am passing the whole rdf mapping object and not
        // only the predicate? Well because i hope i will be able
        // to MAP to RDF also sub fields of a complex field someday
        // and somehow.
        $field_mappings = $context['current_entity_rdf_mapping']->getPreparedFieldMapping($field->getName());
        $field_keys = isset($field_mappings['properties']) ? $field_mappings['properties'] : [$field->getName()];

        if (!empty($field_mappings['datatype'])) {
          $values_clean['@type'] = $field_mappings['datatype'];
        }

        // Well, this is json-ld but $field_item->toArray() depends on
        // each field implementation and some don't have 'value key'
        // Maybe i should handle them as _blank nodes?
        // For now this is a dirty solution.
        if (!empty($field_mappings['datatype_callback'])) {
          $callback = $field_mappings['datatype_callback']['callable'];
          $arguments = isset($field_mappings['datatype_callback']['arguments']) ? $field_mappings['datatype_callback']['arguments'] : NULL;
          $values_clean['@value'] = call_user_func($callback, $values, $arguments);
        }
        $field_context = $this->jsonldContextgenerator->getFieldsRdf(
          $context['current_entity_rdf_mapping'],
          $field->getName(),
          $field->getFieldDefinition(),
          $context['namespaces']
        );

        if (isset($field_context[$field_keys[0]])) {
          $values_clean = $values_clean + $field_context[$field_keys[0]];
        }

      }
      else {
        $field_keys = [$field->getName()];
      }

      // JSON-LD Spec says you can't have an @language for a typed values.
      if (isset($context['langcode']) &&
      (!isset($values_clean['@type']) ||
      empty($values_clean['@type']) ||
      $values_clean['@type'] == "xsd:string" ||
      $values_clean['@type'] == "http://www.w3.org/2001/XMLSchema#string")) {
        // @see https://json-ld.org/spec/latest/json-ld/#dfn-strings.
        // Getting rid of @type to allow @language.
        // @see https://json-ld.org/spec/latest/json-ld/#string-internationalization.
        unset($values_clean['@type']);
        $values_clean['@language'] = $context['langcode'];
      }

      array_filter($values_clean);

      // Convert @value to @id if the item we're normalizing is a Link.
      if (isset($values['uri'])) {
        $values_clean['@id'] = $values_clean['@value'];
        unset($values_clean['@value']);
        unset($values_clean['@type']);
      }

      // The values are wrapped in an array, and then wrapped in another array
      // keyed by field name so that field items can be merged by the
      // FieldNormalizer.
      foreach ($field_keys as $field_name) {
        // If there's no context, we need full predicates, not shortened ones.
        if (!$context['needs_jsonldcontext']) {
          $field_name = $this->escapePrefix($field_name, $context['namespaces']);
          foreach ($values_clean as $key => $val) {
            // Expand values in the array, ie. @type values xsd:string.
            $values_clean[$key] = $this->escapePrefix($val, $context['namespaces']);
          }
        }
        $normalized[$field_name] = [$values_clean];
      }
      return $normalized;
    }
  }
{@inheritdoc}