Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Define how to handle null type #15

Closed
jonaslagoni opened this issue Oct 8, 2021 · 5 comments · Fixed by #23
Closed

Define how to handle null type #15

jonaslagoni opened this issue Oct 8, 2021 · 5 comments · Fixed by #23

Comments

@jonaslagoni
Copy link
Member

We need to figure out how we want to handle the null type overall.

@jonaslagoni jonaslagoni changed the title How do we handle null type for different properties How do we handle null type Oct 8, 2021
@jonaslagoni jonaslagoni changed the title How do we handle null type Define how to handle null type Oct 8, 2021
@jdesrosiers
Copy link
Member

In JSON, null is a different concept than "not present" and the types we generate need to reflect that. In most languages, null or nil is synonymous with "not present". In those languages I would expect code gen to use a custom type that represents the JSON null value.

@jonaslagoni
Copy link
Member Author

So, for null I am not quite sure what is best. If we look at the behavior JSON schema has on the JSON data.

JSON Schema:

{ "properties": { "test": { "type": "null" } } }

validates correctly against

{ "test": null }

and

{  }

In a sense, removing the property completely makes sense to some extend here, as there are no values you want to access is there?

However, with require, removing the property is not possible and it needs to be present:

{ "required": ["test"], "properties": { "test": { "type": "null" } } }

validates correctly against

{ "test": null }

but not

{  }

In a sense, we have the same scenario anyway, where you don't really have an incentive to access such as property in any use-case is there (besides when the class is serialized the property needs to be there)?

In TS we can do the following:

class testType {
  test: null
}

And for Java:

class testType {
  final Object test = null;
}

We could also let custom serializable functionality handle it, and not generate the property at all:

class testType {
  serialize(){
    return '{test: null}'
  }
}

I do however find that a bit weird 🤔 What are your thoughts?

@jdesrosiers
Copy link
Member

You have to remember that JSON Schema describes JSON data and in JSON, null is a value. null is also a type, that contains one value: null. It's just like boolean which is a type that contains two values: true and false. This concept is not compatible with Java's null. In Java, null is not a type. Any type can be null because null means "there isn't anything here". It's equivalent to not defining a property in the instance.

So, in your example, the "test" property definitely needs to be generated because null doesn't mean "there isn't anything here", it means there's a thing here called null. So, in Java I would expect the following.

"test" is null and not required

class TestType {
  JsonNull test = JsonNull.getInstance();
}

"test" is null and required

class TestType {
  @NotNull
  JsonNull test = JsonNull.getInstance();
}

I'm assuming JsonNull is defined by the implementation to be a singleton class. Since there's no equivalent of JSON's null in Java, we have to create something to represent that concept. TypeScript, on the other hand does have the same concept of null as JSON because it's runtime is JavaScript. So, we don't need to create something to represent it.

"test" is null and not required

type TestType = {
  test?: null;
}

"test" is null and required

type TestType = {
  test: null;
}

@jonaslagoni
Copy link
Member Author

Alright, that makes sense 👍 Thanks for clarifying 🙂

@gregsdennis
Copy link
Member

I realize this has been closed for a while, but I thought this was relevant.

null is also important in how many APIs handle 'PUT' and even PATCH requests. For these APIs, { "test": null } means "clear the test property, whereas { } means do nothing.

In some API frameworks (like what's offered out of the box by .Net), this is difficult to discern, though, because they treat null and "absent" as the same when deserializing JSON into models.

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 a pull request may close this issue.

3 participants