Skip to content

Fail on custom scalars without visible properties written with a type or object id - #934

Merged
oryan-block merged 3 commits into
masterfrom
bugfix/932-typed-empty-scalars
Oct 24, 2026
Merged

oryan-block merged 3 commits into
masterfrom
bugfix/932-typed-empty-scalars

Conversation

@oryan-block

@oryan-block oryan-block commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Fixes #932

Follow-up to #931. A custom scalar class without visible properties still lost its value when Jackson wrote a type id or an object id for it:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
class TypedToken(private val value: String = "default")

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator::class)
class IdToken(private val value: String = "default")

These are written as {"@class": "..."} and {"@id": 1}, so the empty bean check from #931 didn't fire (it only looked at {}), and an Optional parameter or an input object field silently got TypedToken("default") or IdToken("default").

Now the check fires for any bean serializer without properties, whatever ids it wrote. So these scalars go down the embedded value path like the ones in #931. In an ObjectNode argument that gives a POJONode with the value. Everywhere else it fails, since Jackson's polymorphic and object id deserializers can't read an embedded value (missing type id property '@class', Cannot deserialize value of type Integer). I think an error is better than a silent default here.

I did have them working (native type ids on the embedded value, and binding the value to a generated object id), but it was a fair bit of Jackson plumbing with its own gaps, for scalars I don't think anyone has. So I dropped it. If someone runs into it, removing the annotation or adding a getter for the value works.

Release note: custom scalars without visible properties that Jackson writes with a type id (@JsonTypeInfo) or an object id (@JsonIdentityInfo) now fail with an error instead of reaching the resolver as a default instance. In ObjectNode arguments they're passed with their value.

Checklist

  • Pull requests follows the contribution guide
  • New or modified functionality is covered by tests

Both new cases in CustomScalarInputTest fail on master: the Optional, input object and list cases with @JsonTypeInfo / @JsonIdentityInfo return default or error inconsistently, and the ObjectNode case gets {"@id":1} or errors. mvn clean verify passes (432 tests). Also checked through the installed jar in a separate consumer project: on master the Optional parameters return typed default and id default, with this change they fail with the errors above.

@oryan-block oryan-block changed the title Keep the values of custom scalars without visible properties written with a type or object id Fail on custom scalars without visible properties written with a type or object id Oct 24, 2026
@sonarqubecloud

Copy link
Copy Markdown

@oryan-block
oryan-block merged commit f6f4fa4 into master Oct 24, 2026
5 checks passed
@oryan-block
oryan-block deleted the bugfix/932-typed-empty-scalars branch October 24, 2026 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Custom scalars without visible properties lose their value when written with a type or object id

1 participant