Core: JSON POST not working since version 2.4.7

Created on 1 Oct 2019  路  16Comments  路  Source: api-platform/core

Since version 2.4.7 the fallowing POST request with application/json is not working anymore:

{
"title": "Test document",
"articles": [
     {
        "title": "New Article", 
        "originalArticle": {"id": 21}
     }
  ]
}

Throws an error:

No route matches "21".

Version 2.4.6 is working.

bug invalid question

Most helpful comment

Even if it is new, this shouldn't be done in a patch release. Definitely a BC break.

All 16 comments

Having the same issue (2.4.6 works, >= 2.4.7 does not).

Using IRI instead of raw ID seems to be working though. Is this a new preferred way of doing things or is it bugged?

{
  "firstname": "Test",
  "groups": [
    {
      "id": '/groups/1',
      "title": "Standard"
    }
  ]
}

Even if it is new, this shouldn't be done in a patch release. Definitely a BC break.

It looks like a bug to me. Does some want to work on a fix? At least a failing test would help.

Can you confirm that you have this config?

api_platform:
    allow_plain_identifiers: true

If so, please share the stack trace.

@dunglas I'm volunteer to work on it, but I could not reproduce the bug on 2.4.6 (expected IRI in payload).

@bz4r @maks-rafalko @nicklasaloq could you please provide a repository exposing the failure? Or, at least, your full API-Platform package configuration / resource configuration?

I have tried this:

POST https://localhost:8002/api/reviews
Accept: application/json
Content-Type: application/json

{
  "book": 1,
  "text": "Awesome!"
}

It works in 2.4.6 and 2.4.7 as soon as allow_plain_identifiers is turned on, as @teohhanhui pointed out, and your Content-Type header is application/json (not application/ld+json).

Beware that the example you provided is not correct: the server doesn't expect "book": {"id": 1} but "book": 1.

@nicklasaloq Referencing the object by its IRI, e.g. "book": "/api/books/1" is the recommended way indeed.

Still does not work for me even with allow_plain_identifiers turned on. I also made sure to send application/json accept and content-type headers. Still does not work.

@bpolaszek
If "book": {"id": 1} is not right, how come it has been working up until now (all i am saying is, something must have changed)?

Changing this:

{
  "firstname": "Test",
  "groups": [
    {
      "id": 1,
      "title": "Standard"
    }
  ]
}

into this:

{
  "firstname": "Test",
  "groups": [
    {
      "id": "/groups/1",
      "title": "Standard"
    }
  ]
}

makes it work. I guess I'll redo all requests to use that standard!

@nicklasaloq

If "book": {"id": 1} is not right, how come it has been working up until now (all i am saying is, something must have changed)?

It was never supposed to work that way, as far as I could tell. It just happened to be working, but that's never been a supported use case (you can look at our test suite).

After discussion with @dunglas, it's supposed to work if you have configured a serializer group in the denormalization context which allows embedding the Book resource. Is that your use case?

Indeed, if this specific use case is broken, it's a bug.

To expand on the earlier examples, this is the resource config and groups relation in my User entity. To the best of my knowledge this is exactly what you described? A serializer group in the denormalization context, right?

@ApiResource(
 *     attributes={
 *          "pagination_items_per_page"=100,
 *          "model_names"={
 *              "outin"="out",
 *              "in"="in",
 *              "public"="public"
 *          },
 *         "normalization_context"={"groups"={"out", "in"}},
 *         "denormalization_context"={"groups"={"in"}},
 *         "pagination_enabled"=true
 *      },
 *     collectionOperations={
 *          "post"={"method"="POST"},
 *          "get"={"method"="GET"},
 *          "public"={"method"="GET","route_name"="user_public_information","normalization_context"={"groups"={"public"}}}
 *      },
 *     itemOperations={
 *          "get"={"method"="GET"},
 *          "put"={"method"="PUT"},
 *          "delete"={"method"="DELETE"},
 *      }
 * )
    /**
     * @var ArrayCollection|Group[]
     * @ORM\ManyToMany(targetEntity="App\Entity\Group",inversedBy="users")
     * @ORM\JoinTable(name="user_group_assoc",
     *      joinColumns={@ORM\JoinColumn(name="userId", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="groupId", referencedColumnName="id")}
     * )
     * @Groups({"in"})
     */
    protected $groups;

Looks like I was the one who broke it: https://github.com/api-platform/core/blame/c1b89a13772f6ba9eb39fddbf83e3fad9faf3c00/src/Serializer/ItemNormalizer.php#L80

So I'm going to look into this. :laughing:

After discussion with @dunglas, it's supposed to work if you have configured a serializer group in the denormalization context which allows embedding the Book resource. Is that your use case?

Indeed, if this specific use case is broken, it's a bug.

Yes this was my use case. i have serializer groups on the article

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Article", inversedBy="documentArticles", fetch="EXTRA_LAZY")
     * @ORM\JoinColumn(name="article_id", referencedColumnName="id", onDelete="SET NULL")
     * @Groups({"document_article", "document"})
     **/
    public $originalArticle;

And this worked on version 2.4.6

My investigation has revealed that it's not a bug. In fact, it's because we've fixed a bug which in turn revealed the problem with incorrect property metadata set on your API resources.

See #3145

please check #3145 and let us know if more issues araise.

Thanks for the investigation @teohhanhui !

Just to bring maintainers' attention to patch BC breaks again: https://twitter.com/maks_rafalko/status/1200880397963407362?s=20

Upgrading from 2.4.3 to 2.4.7

docker 2019-12-01 00-20-18
phpunit

This is not how the patch update should look like, no matter whether you are fixing a bug or not.

Patch seems to work fine with other content types too:

api_platform:
    allow_plain_identifiers: true
    patch_formats:
        jsonld:   ['application/ld+json']
        jsonapi:  ['application/vnd.api+json']
        json:     ['application/merge-patch+json']
Was this page helpful?
0 / 5 - 0 ratings

Related issues

theshaunwalker picture theshaunwalker  路  3Comments

vViktorPL picture vViktorPL  路  3Comments

CvekCoding picture CvekCoding  路  3Comments

gustawdaniel picture gustawdaniel  路  3Comments

mahmoodbazdar picture mahmoodbazdar  路  3Comments