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

Deserialize empty JSON schemas #110

Closed
wants to merge 1 commit into from
Closed

Deserialize empty JSON schemas #110

wants to merge 1 commit into from

Conversation

quilicicf
Copy link

Affects: 2.8.2

Issue

Spec pointer

If the property is not defined or is not in this list, then any
type of value is acceptable.

I'd expect an empty JSON schema to be deserialized as AnySchema.

How to reproduce

POM file

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>fr.quilicicf.test</groupId>
    <artifactId>jackson-module-jsonSchema</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-jsonSchema</artifactId>
            <version>2.8.2</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>

Java file

package fr.quilicicf.test;

import org.junit.Assert;
import org.junit.Test;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.types.AnySchema;

public class JsonSchemaDeserialization {

    @Test
    public void test() throws Exception {
        JsonSchema jsonSchema = new ObjectMapper().readValue("{}", JsonSchema.class);
        Assert.assertTrue(jsonSchema instanceof AnySchema);
    }
}

Trace

com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'type' that is to contain type id  (for class com.fasterxml.jackson.module.jsonSchema.JsonSchema)
 at [Source: {}; line: 1, column: 2]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:261)
    at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:1340)
    at com.fasterxml.jackson.databind.DeserializationContext.reportWrongTokenException(DeserializationContext.java:1196)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedUsingDefaultImpl(AsPropertyTypeDeserializer.java:157)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:105)
    at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:142)
    at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:63)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3789)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2833)
    at fr.quilicicf.test.JsonSchemaDeserialization.test(JsonSchemaDeserialization.java:23)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

@cowtowncoder
Copy link
Member

Sounds reasonable for specific case of empty Object, but would this cause problems for other kinds of invalid schema JSON? Default implementation is used in every case where type identifier is missing.
Perhaps this is not a big problem (any JSON properties found would likely not have counterpart in AnySchema.

@quilicicf
Copy link
Author

JSON schemas without type being of type any was my interpretation of the spec. Maybe I'm wrong.
I'll look at the failing tests.

@quilicicf
Copy link
Author

quilicicf commented Aug 31, 2016

Looks like one cannot deserialize directly in any subtype of JsonSchema anymore, only in JsonSchema itself.

When trying to MAPPER.readValue(str, ObjectSchema.class) it says

AnySchema is not a subtype of ObjectSchema.

I'm wondering if defaultImpl should be applied to subclasses of JsonSchema but I don't know Jackson enough to make a clean fix on that issue I'm afraid. Any suggestion ?

@cowtowncoder
Copy link
Member

@quilicicf Right, you can not ask for ObjectSchema, and then be handed AnySchema since latter is not a subtype of former -- you can not cast AnySchema into ObjectSchema.
This is... a problematic case, and ideally I think there should be a way to try to handle this. But as things are, I am not sure how that could be achieved.

Ideally, I think, it should be possible to specify defaultImpl that obeys contract at @JsonTypeInfo (true here), but also request a subtype, and only fail if there is an actual problem (that is, attempt was made to use invalid defauilt implementation) -- but work if type actually does match.
Problem comes from the fact that code at low level only sees the potential problem, of base type not the one where @JsonTypeInfo was declared, but one that user specified (ObjectSchema), and correctly (wrt information it has) determines that two are not compatible.

I'll have to think about this, but it is probably safe to say that fix, if one is found, will not be found on short term.

@quilicicf
Copy link
Author

OK for me. The fix I did works for us because we always deserialize into class JsonSchema so nothing urgent on our side, we forked the module.

If you find a complete fix, we'd be glad to switch back to the official implementation though.

Thanks for your time.

@quilicicf
Copy link
Author

And as I'm being told, we'd like to get rid of that fork ASAP.

@quilicicf quilicicf closed this Jun 13, 2017
@quilicicf quilicicf deleted the master_deserialize_empty_schemas branch June 13, 2017 08:31
@quilicicf quilicicf restored the master_deserialize_empty_schemas branch June 13, 2017 08:31
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.

2 participants