Closed jschroeder1 closed 2 years ago
Thx for reporting this, I'll take a look at it asap.
You are right: When you want to serialize an EntityModel
to JSON:API, an id
MUST be present in all cases, except if you do a POST. But if I relax the check to allow serialization without id
, your use case would work but in all the other use cases, an invalid JSON:API would be created. This is why the library checks if a valid id
can be computed. Since serializing an object to be used for a POST is the exception, I would like to keep the current default behavior since it helps the users to figure out quickly if their Java RepresentationModels
can be serialized correctly to JSON:API.
But I understand your point and try to find a configuration option that disables the id check, so that an object without valid id could also be serialized to be used in a POST request.
One way of implementing this could be to configure a marker id value like ignoreJsonApiId
or -1
to indicate that the id should not be serialized at all. So
TestModel.builder().id("ignoreJsonApiId").attribute("whatever").build();
would the be serialized without id
.
But let me thing a bit longer about it, may be I find a better solution.
Please stay tuned...
You can now add configuration like
new JsonApiConfiguration().withJsonApiIdNotSerializedForValue("ignoreJsonApiId")
Then the above example will be serializes as
{
"data":{
"type":"testmodels",
"attributes":{
"attribute":"whatever"
}
}
}
@toedter Thank you! Looks like exactly what I need.
I tried it out and I'm able to build the jsonApiModel but when I attempt to POST with RestTemplate, I'm hitting a slightly different exception. Here's what I've got:
In my @Configuration
@Bean
public JsonApiMediaTypeConfiguration jsonApiMediaTypeConfiguration(
ObjectProvider<JsonApiConfiguration> configuration,
AutowireCapableBeanFactory beanFactory) {
return new JsonApiMediaTypeConfiguration(configuration, beanFactory);
}
@Bean
public JsonApiConfiguration jsonApiConfiguration() {
return new JsonApiConfiguration().withJsonApiIdNotSerializedForValue("ignoreJsonApiId");
}
in the test class:
TestModel testModel = TestModel.builder().attribute("whatever").build();
final HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", MediaTypes.JSON_API_VALUE);
RepresentationModel<?> test = jsonApiModel().model(testModel).build();
restTemplate.exchange("/mypostroute",
HttpMethod.POST,
new HttpEntity<>(test, headers),
new TypeReferences.EntityModelType<>() {});
which now results in an IllegalStateException
instead of an HttpMessageNotWritableException
:
Caused by: java.lang.IllegalStateException: Cannot compute JSON:API resource id.::: TestModel(id=null, attribute=whatever)
at com.toedter.spring.hateoas.jsonapi.JsonApiResourceIdentifier.getResourceField(JsonApiResourceIdentifier.java:189)
at com.toedter.spring.hateoas.jsonapi.JsonApiResourceIdentifier.getId(JsonApiResourceIdentifier.java:92)
at com.toedter.spring.hateoas.jsonapi.JsonApiData.extractContent(JsonApiData.java:158)
at com.toedter.spring.hateoas.jsonapi.AbstractJsonApiModelSerializer.serialize(AbstractJsonApiModelSerializer.java:96)
at com.toedter.spring.hateoas.jsonapi.AbstractJsonApiModelSerializer.serialize(AbstractJsonApiModelSerializer.java:35)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
... 80 more
Does that look correct to you or is there something I should be doing differently?
Thanks again.
This looks correct, since the id of your test model cannot be null. If you want the id to be ignored it must exactlxy match the value you specified in the configuration. So, If you initialize you testModel like
TestModel testModel = TestModel.builder().id("ignoreJsonApiId").attribute("whatever").build();
it should serialize without id. Be aware that you can chose the value that is checked for yourself, e.g.
JsonApiConfiguration().withJsonApiIdNotSerializedForValue("-1");
...
TestModel testModel = TestModel.builder().id("-1").attribute("whatever").build();
would also work.
Oh right, of course. Missed that part. It's working perfectly now.
Thanks!
I just released version 1.5.0 including this.
Hi,
I'm attempting to use RestTemplate to Integration Test some endpoints I've set up. I've configured it as specified in the docs and it's mostly working fine but I'm trying to create a resource via a POST route that accepts
application/vnd.api+json
and I'm running into an issue.Example:
The resource is new and doesn't haven an ID at this point so I would expect it to serialize like this:
which I believe should be valid according to the JSON:API spec.
But when I execute the code, it results in an exception:
If I set id to an empty string, it will serialize successfully.
Is there a way to do this?