jackson-module-jsonSchema
jackson-module-jsonSchema copied to clipboard
Instant serialized to wrong type
version
2.8
Description
I have serialized the following entity :
{
"createdDate": {
"nano": 326000000,
"epochSecond": 1484986332
},
"lastModifiedDate": null,
"createdById": null,
"lastModifiedById": null,
"active": true,
"login": "admin",
"roleList": [
"ROLE_MANAGER",
"ROLE_ADMIN"
],
"username": "admin",
"enabled": true,
"authorities": [
{
"authority": "ROLE_MANAGER"
},
{
"authority": "ROLE_ADMIN"
}
],
"accountNonLocked": true,
"credentialsNonExpired": true,
"accountNonExpired": true,
"new": false
}
And it's schema json :
{
"title": "Manager",
"properties": {
"new": {
"title": "New",
"readOnly": true,
"type": "boolean"
},
"lastModifiedDate": {
"title": "Last modified date",
"readOnly": false,
"type": "string",
"format": "date-time",
"$ref": "#/definitions/instant"
},
"credentialsNonExpired": {
"title": "Credentials non expired",
"readOnly": true,
"type": "boolean"
},
"active": {
"title": "Active",
"readOnly": false,
"type": "boolean"
},
"login": {
"title": "Login",
"readOnly": false,
"type": "string"
},
"roleList": {
"title": "Role list",
"readOnly": false,
"type": "array",
"items": {
"type": "string"
}
},
"enabled": {
"title": "Enabled",
"readOnly": true,
"type": "boolean"
},
"authorities": {
"title": "Authorities",
"readOnly": true,
"type": "array",
"items": {
"type": "object"
}
},
"createdDate": {
"title": "Created date",
"readOnly": false,
"type": "string",
"format": "date-time",
"$ref": "#/definitions/instant"
},
"lastModifiedById": {
"title": "Last modified by id",
"readOnly": false,
"type": "integer"
},
"accountNonExpired": {
"title": "Account non expired",
"readOnly": true,
"type": "boolean"
},
"createdById": {
"title": "Created by id",
"readOnly": false,
"type": "integer"
},
"username": {
"title": "Username",
"readOnly": true,
"type": "string"
},
"accountNonLocked": {
"title": "Account non locked",
"readOnly": true,
"type": "boolean"
}
},
"definitions": {
"instant": {
"type": "string",
"properties": {
"nano": {
"title": "Nano",
"readOnly": true,
"type": "integer"
},
"epochSecond": {
"title": "Epoch second",
"readOnly": true,
"type": "integer"
}
}
}
},
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#"
}
I have test on http://www.jsonschemavalidator.net/ :
Found 2 error(s)
Message:
Invalid type. Expected String but got Object.
Schema path:
#/definitions/instant/type
Message:
Invalid type. Expected String but got Object.
Schema path:
#/definitions/instant/type
It appear jackson try to serialize a java Instant but the generated schema contain the wrong type "object" instead of "string"
This is most likely since you have not registered module jackson-datatype-jsr310 (from https://github.com/FasterXML/jackson-modules-java8). Without it, Java 8 type Instant is not supoorted, as databind only requires Java 7 and can not (by default) add handles for Java 8 types.
This is most likely since you have not registered module jackson-datatype-jsr310 (from https://github.com/FasterXML/jackson-modules-java8). Without it, Java 8 type Instant is not supoorted, as databind only requires Java 7 and can not (by default) add handles for Java 8 types
I have jackson-datatype-jsr310 installed. My Java 8 type Instant are working well in my software.
Is there anything else I have to do in order for this to work ?
@kopax that should be all... what does the original Class (for which schema is generated) look like?
Looking at generated schema it looks as if Instant type was considered a POJO, but InstantSerializerBase seems to have logic to produce proper information.
I assume this is reproducible with 2.8.7? (all components, specifically jackson-datatype-jsr310 important here)
My class look like this :
public abstract class VersionId extends LongId implements Cloneable {
private static final Logger logger = LoggerFactory.getLogger(VersionId.class);
@Version
@NotNull
@JdbcType(BIGINT)
@Column(name = "VERSION")
private Integer version;
@CreatedDate
@NotNull
@JdbcType(TIMESTAMP)
@Column(name = "CREATED_DATE")
@JsonUnwrapped
private Instant createdDate;
@LastModifiedDate
@NotNull
@JdbcType(TIMESTAMP)
@JsonUnwrapped
@Column(name = "LAST_MODIFIED_DATE")
private Instant lastModifiedDate;
@CreatedBy
@Column(name = "CREATED_BY")
@NotNull
@JdbcType(BIGINT)
private Long createdById;
@Column(name = "LAST_MODIFIED_BY")
@LastModifiedBy
@JdbcType(BIGINT)
private Long lastModifiedById;
@JdbcType(BOOLEAN)
@Column(name = "ACTIVE")
@NotNull
private Boolean active = true;
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public Instant getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Instant createdDate) {
this.createdDate = createdDate;
}
public Instant getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(Instant lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
public Long getCreatedById() {
return createdById;
}
public void setCreatedById(Long createdById) {
this.createdById = createdById;
}
public Long getLastModifiedById() {
return lastModifiedById;
}
public void setLastModifiedById(Long lastModifiedById) {
this.lastModifiedById = lastModifiedById;
}
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
}
It is reproducible with 2.8.7. It sounds like the type string is wrong .
One thing to note is that @JsonUnwrapped has not effect here: Instants are not serialized as Beans by Jackson. But I don't think that affects schema generation.
Using @JsonUnwrapped allow me to have the date like this :
"createdDate": "2017-03-22T06:04:30.369Z",
Instead of something like
"createdDate": { "instant": "2017-03-22T06:04:30.369Z" }
But the json schema is still invalid. Why does it show string while it has some object metadata ?
@kopax That's not due to JsonUnwrapped; it should be just basic text format. Unwrapping only works for standard Beans, and if you do have jsr310 module, Instant should never be serialized as such. You can test that by removing annotations, should not make any difference.
But looking back the original problem, this is weird:
"definitions": {
"instant": {
"type": "string",
"properties": {
"nano": {
"title": "Nano",
"readOnly": true,
"type": "integer"
},
"epochSecond": {
"title": "Epoch second",
"readOnly": true,
"type": "integer"
}
}
}
},
where type of string should not have properties. But I don't know how or why this would come about... I don't even know what definitions means here.
It's a jsonschema. I think it's jackson json that generate it. It's in a spring boot base application. (spring-data-rest)
@kopax Another strange thing there is this:
"$schema": "http://json-schema.org/draft-04/schema#"
which is not something Jackson's schema module outputs: it only supports v3 of schema spec.
(see JsonSchema.java).
I also can not see anything in schema module that would actually output definitions property.
Perhaps spring-data-rest (or core Spring package(s) it depends on) might be using a different JSON Schema generator?