Score:0

Custom field type that has an array property won't save unless serialized, otherwise get "This value should be of the correct primitive type" error

in flag

I have a custom field type with two properties I am storing on it. One stores a string. The other I want to store an array. The array should be serialized in the field value table of the database, but it should be an array when exported to YAML (default value setting of the field instance configuration).

I am having trouble getting this to work. In my head it would be similar to 'allowed formats' option on text long instances.

The field value schema:

field.value.myfieldtype:
  type: mapping
  label: Default value
  mapping:
    view_id:
      type: string
      label: View ID
    facets:
      type: sequence
      label: Facet list
      sequence:
        type: string
        label: 'Facet machine name'

The field properties are defined as:

  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {

    $properties['view_id'] = DataDefinition::create('string')
      ->setLabel(t('A Drupal View.'))
      ->setRequired(TRUE);

    $properties['facets'] = DataDefinition::create('string')
      ->setLabel(t('A list of facets selected by the user.'))
      ->setRequired(FALSE);

    return $properties;
  }

In the custom form widget I made, I have massageFormValues like this:

  /**
   * {@inheritdoc}
   */
  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
    $facet_list = !empty($values[0]['facets']) ? array_filter($values[0]['facets']) : [];
    $values[0]['facets'] = serialize($facet_list);
    return parent::massageFormValues($values, $form, $form_state);
  } 

If I call array_keys instead of serialize, or pass anything that is not a string, I get an error on save:

This value should be of the correct primitive type. 

If I use serialize, it saves fine and I can see the serialized value in the tuple in the database. However, if I set a 'Default Value' on the field instance and run a configuration export, I get this:

default_value:
  -
    view_id: 'search:content_listing'
    facets: 'a:1:{s:16:"content_category";s:16:"content_category";}'

What I would expect is:

default_value:
  -
    view_id: 'search:content_listing'
    facets: 
      - content_category
      - (other selected options)
      - (other selected options)

What am I missing?

Score:2
in flag

Instead of serializing, I changed the schema of the property to store as JSON for sake of the storage and export since serialized strings are discouraged.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.