protected function _mergeJoinData($original, $assoc, $value, $options)
    {
        $associated = isset($options['associated']) ? $options['associated'] : [];
        $extra = [];
        foreach ($original as $entity) {
            // Mark joinData as accessible so we can marshal it properly.
            $entity->setAccess('_joinData', true);

            $joinData = $entity->get('_joinData');
            if ($joinData && $joinData instanceof EntityInterface) {
                $extra[spl_object_hash($entity)] = $joinData;
            }
        }

        $joint = $assoc->junction();
        $marshaller = $joint->marshaller();

        $nested = [];
        if (isset($associated['_joinData'])) {
            $nested = (array)$associated['_joinData'];
        }

        $options['accessibleFields'] = ['_joinData' => true];

        $records = $this->mergeMany($original, $value, $options);
        foreach ($records as $record) {
            $hash = spl_object_hash($record);
            $value = $record->get('_joinData');

            // Already an entity, no further marshalling required.
            if ($value instanceof EntityInterface) {
                continue;
            }

            // Scalar data can't be handled
            if (!is_array($value)) {
                $record->unsetProperty('_joinData');
                continue;
            }

            // Marshal data into the old object, or make a new joinData object.
            if (isset($extra[$hash])) {
                $record->set('_joinData', $marshaller->merge($extra[$hash], $value, $nested));
            } elseif (is_array($value)) {
                $joinData = $marshaller->one($value, $nested);
                $record->set('_joinData', $joinData);
            }
        }

        return $records;
    }