Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add support for generic tristate (undefined | null | defined) codec #107

Open
myuwono opened this issue Nov 26, 2022 · 2 comments · May be fixed by #108
Open

Add support for generic tristate (undefined | null | defined) codec #107

myuwono opened this issue Nov 26, 2022 · 2 comments · May be fixed by #108
Assignees
Labels
enhancement New feature or request

Comments

@myuwono
Copy link
Collaborator

myuwono commented Nov 26, 2022

Feature Request

  • add support for serialization / deseiralization of TriState<A> which models Absent | Null | Defined<A>

Context

There are times where users need to model an API that need differentiate between:

  • absence of a field
  • presence of a field in json, but being set to null
  • presence of a field in json, with a value set

An example is a PATCH endpoint that may have the following contract:

// modify nickname
PATCH /api/user/{id} { "nickname" : "john doe" }

// deletes nickname
PATCH /api/user/{id} { "nickname" : null }

// does nothing
PATCH /api/user/{id} { }

Currently nullables T? is not a viable alternative as they are missing a degree of freedom (the absence) and hence isn't usable. As well, Option<T> is generally used to treat missing and absence as None by convention. While Option<T?> is likely to be a possible container type for this, it is somewhat not feasible to be used due to null being a synthetic type. I.e. somehow Jackson could not differentiate whether the type signature requested is nullable or not at runtime, or at least I could not find a way to do so with my limited knowledge.

A possible alternative would be to define a TriState<A> as follows:

sealed class TriState<out A> {
  companion object

  object Absent : TriState<Nothing>()
  object Null : TriState<Nothing>()
  data class Defined<T>(val value: T) : TriState<T>()
}

Given the code above we'd have a concrete distinction between Absent or Null that Jackson can use. This makes modelling the above behaviour possible. Additionally, this model can be bi-directionally converted to Arrow's Option<T?> or Option<Option<T>> without loss of precision which hopefully should support the ergonomic and integration with the rest of the arrow ecosystem.

Another alternative would be to expose a module that users can use to implement such sealed class within their own codebase e.g. GenericTriStateModule<T>.

@myuwono myuwono added the enhancement New feature or request label Nov 26, 2022
@myuwono myuwono self-assigned this Nov 27, 2022
@myuwono myuwono changed the title Add special data type to support generic tristate serialization / deserialization Add support for generic tristate (undefined | null | defined) serialization / deserialization Nov 27, 2022
@myuwono myuwono changed the title Add support for generic tristate (undefined | null | defined) serialization / deserialization Add support for generic tristate (undefined | null | defined) codec Nov 27, 2022
@myuwono myuwono linked a pull request Nov 27, 2022 that will close this issue
@christophejan
Copy link

Hello @myuwono, I just quickly read this issue and that make me think of jackson-databind-nullable. I don’t know if you already check this module but perhaps it can help.

@myuwono
Copy link
Collaborator Author

myuwono commented Dec 14, 2022

Thank you @christophejan I wasn't aware of that project. That one is interesting. JsonNullable<T> does have the similar objective, approached using using the Java Optional-ish approach instead of Kotlin sealed class. I was initially on the fence whether or not a new type would be necessary. After looking into that library, it appears that a new dedicated type would indeed be a good addition to arrow-integrations-jackson. We will need a good name for it.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants