You can create a custom Normalizer to use and Views will respect that. Within that, you can create the output structure however you like.
Here is an example class, where "Collection" is the content type:
<?php
declare(strict_types = 1);
namespace Drupal\mymodule\Normalizer;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Url;
use Drupal\image\Entity\ImageStyle;
use Drupal\serialization\Normalizer\ContentEntityNormalizer;
use Drupal\node\NodeInterface;
/**
* Class CollectionNormalizer.
*
* @package Drupal\mymodule\Normalizer
*/
class CollectionNormalizer extends ContentEntityNormalizer {
/**
* The interface or class that this Normalizer supports.
*
* @var string
*/
protected $supportedInterfaceOrClass = [
'Drupal\node\NodeInterface',
];
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* {@inheritdoc}
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
public function supportsNormalization($data, $format = NULL) {
if (!is_object($data) || !$this->checkFormat($format)) {
return FALSE;
}
if ($data instanceof NodeInterface && $data->getType() == 'collection') {
return TRUE;
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function normalize($entity, $format = NULL, array $context = []) {
$attributes = [];
$attributes['id'] = $entity->id();
$attributes['title'] = $entity->label();
$attributes['summary'] = $entity->get('field_summary')->value;
$attributes['card_type'] = $entity->get('field_directory_view')->value;
$attributes['list_image'] = NULL;
$attributes['url'] = Url::fromRoute('entity.node.canonical', ['node' => $attributes['id']])->toString();
$media = $entity->get('field_featured_image')->getValue();
if (!empty($media)) {
$item = $this->entityTypeManager->getStorage('media')->load($media[0]['target_id']);
$image = $item->get('image')->getValue();
$attributes['list_image'] = [
'src' => ImageStyle::load('collection_listing')
->buildUrl($item->image->entity->getFileUri()),
'alt' => $image[0]['alt'],
];
}
return $attributes;
}
}
You also have to declare it in your modules services.yml file:
mymodule.collection_entity:
class: Drupal\mymodule\Normalizer\CollectionNormalizer
arguments: ['@entity_type.manager']
tags:
- { name: normalizer, priority: 10 }
You can inject whatever other services you need, used entityTypeManager as an example.
Views will use this instead of the default, so long as the priority is higher. IMO this is far easier than trying to use the Views UI to get the output you want from a REST Export display. You are free to construct the output in whatever way you wish.
So in your case, you would replace "Collection" with "Boat" and check that the content type is 'boat', then build the response as you need it.