it-swarm.com.de

Benutzerdefiniert REST POST Ressource zum Akzeptieren von JSON

Ich versuche, eine einfache Suche zu erstellen. Autocomplete POST Endpunkt, der JSON akzeptiert und JSON ausgibt, aber ich habe Probleme, Drupal 8) zu erhalten, um nur einfaches JSON zu akzeptieren.

Derzeit wird ein 404-Fehler für diesen Endpunkt angezeigt, obwohl er in REST UI und ich habe die Berechtigung aktiviert. Wenn ich serialization_class Mit dem Wert Drupal\node\Entity\Node Hinzufüge. Zum Klassenkommentar erhalte ich den Fehler 415, weil ein Knoten erwartet wird. Okay, großartig. Wie kann ich JSON tatsächlich akzeptieren? Muss ich wirklich einen Entitätstyp nur für meine automatische Vervollständigungssuche erstellen?

Hier ist der Code, den ich in mymodule/src/Plugin/rest/resource/SearchAutocompleteResource.php habe.

namespace Drupal\MyModule\Plugin\rest\resource;

use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Drupal\node\Entity\Node;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Provides a resource for search autocomplete.
 *
 * @RestResource(
 *   id = "mymodule:searchautocomplete",
 *   label = @Translation("MyModule: Search Autocomplete"),
 *   uri_paths = {
 *     "canonical" = "/api/v1/search-autocomplete",
 *     "https://www.drupal.org/link-relations/create" = "/api/v1/search-autocomplete"
 *   }
 * )
 */
class SearchAutocompleteResource extends ResourceBase {

  public function post($search = null) {

    return new ResourceResponse(array(
      'example' => 'return value'
    ));

  }

}
5
Risse

Bis Serialization_class optional machen (# 2419825) Problem für den Zweig 8.2.x Behoben wurde, konnten Sie nicht durchkommen, ohne eine benutzerdefinierte Serialisierungsklasse zu erstellen, die lediglich die bereitgestellten Daten übergibt, um die Anforderung zu erfüllen für die obligatorische Serialisierung.

Wenn Sie es für Drupal <= 8.1) verwenden möchten, versuchen Sie Folgendes:

  1. Erstellen Sie einen benutzerdefinierten Normalisierer.
  2. Stellen Sie es dem System als Service zur Verfügung.
  3. Verwenden Sie es als serialization_class Für Ihre Rest-Ressource.

modules/mymodule/src/normalizer/JsonDenormalizer.php:

<?php

namespace Drupal\mymodule\normalizer;

use Drupal\serialization\Normalizer\NormalizerBase;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

/**
 * Class JsonDenormalizer
 *
 * @todo Remove this class once https://www.drupal.org/node/2419825 is fixed.
 */
class JsonDenormalizer extends NormalizerBase implements DenormalizerInterface {

  /**
   * The interface or class that this Normalizer supports.
   *
   * @var array
   */
  protected $supportedInterfaceOrClass = array(__CLASS__);

  /**
   * {@inheritdoc}
   */
  public function normalize($object, $format = null, array $context = array()) {
    return parent::normalize($object, $format, $context);
  }

  /**
   * {@inheritdoc}
   */
  public function denormalize($data, $class, $format = NULL, array $context  = array()) {
    return $data;
  }
}

modules/mymodule/mymodule.services.yml:

services:
  # can be removed once https://www.drupal.org/node/2419825 is fixed.
  serializer.normalizer.mymodule.json:
    class: Drupal\mymodule\normalizer\JsonDenormalizer
    tags:
      - { name: normalizer }

mymodule/src/Plugin/rest/resource/SearchAutocompleteResource.php:

/**
 * Provides a resource for search autocomplete.
 *
 * @RestResource(
 *   id = "mymodule:searchautocomplete",
 *   label = @Translation("MyModule: Search Autocomplete"),
 *   serialization_class = "Drupal\mymodule\normalizer\JsonDenormalizer",
 *   uri_paths = {
 *     "canonical" = "/api/v1/search-autocomplete",
 *     "https://www.drupal.org/link-relations/create" = "/api/v1/search-autocomplete"
 *   }
 * )
 */
7
maijs

Die Antwort von @maijs ist korrekt für Drupal 8.1.x und niedriger, aber für 8.2.x ist es also viel einfacher, weil Sie nicht einmal an den Normalisierer denken müssen. Hier ist ein Beispiel für my_module/src/Plugin/rest/resource/MyRestResource.php

<?php

namespace Drupal\my_module\Plugin\rest\resource;

use Drupal\Core\Session\AccountProxyInterface;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Psr\Log\LoggerInterface;

/**
 * Provides a resource to get view modes by entity and bundle.
 *
 * @RestResource(
 *   id = "my_rest_resource",
 *   label = @Translation("My rest resource"),
 *   serialization_class = "",
 *   uri_paths = {
 *     "canonical" = "/my_rest_resource"
 *   }
 * )
 */
class MyRestResource extends ResourceBase {

  /**
   * A current user instance.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * Constructs a Drupal\rest\Plugin\ResourceBase object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param array $serializer_formats
   *   The available serialization formats.
   * @param \Psr\Log\LoggerInterface $logger
   *   A logger instance.
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   A current user instance.
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    array $serializer_formats,
    LoggerInterface $logger,
    AccountProxyInterface $current_user) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);

    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->getParameter('serializer.formats'),
      $container->get('logger.factory')->get('my_module'),
      $container->get('current_user')
    );
  }

  /**
   * Responds to GET requests.
   *
   * Returns a list of bundles for specified entity.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\HttpException
   *   Throws exception expected.
   */
  public function get() {
    $response = 'hello world';
    return new ResourceResponse($response);
  }

  public function post(array $data = []) {
    $response = array(
      "hello_world" => $data,
    );
    return new ResourceResponse($response);
  }

  public function patch($arg) {
    return new ResourceResponse('hello patch');
  }

}

Der Schlüssel hier ist post(array $data = []) am Ende der Datei. In 8.1.x war das unmöglich, aber in 8.2.x ist das alles, was man braucht, um Post-Daten in ein Array zu konvertieren. So sieht es aus, wenn Sie diese URL beim Postboten anfordern:

(enter image description here

3
Matt Korostoff

Dies habe ich getan, um ein JSON-Objekt von einem Beitrag zu erhalten.

use Symfony\Component\HttpFoundation\Request;

class AjaxController extends ControllerBase {
    public function save(Request $request) {
        $object = json_decode($request->getContent());
1
Matt F