1

Jackson reads input numbers as Strings. As an example below Student class read name 4567 as a String.

ex: input

{
name: 4567
...
}

Java class

Class Student {

String name;
...
}

Jackson is parsing the JSON text and mapping the number value to the string field, and I don't want the type conversion, i.e. for the number to be converted to a string. In this scenario Jackson converts the value from int (4567) to String("4567"). How this behavior can changes to throw an exception if other type provided to fail ?

era
  • 391
  • 4
  • 24
  • You want to check if the user inputs a name only containing letters? – J. Doe Mar 28 '19 at 18:38
  • @OamarKanji In computing, Jackson is a high-performance JSON processor for Java. Its developers extol the combination of fast, correct, lightweight, and ergonomic attributes of the library. -Wikipedia – J. Doe Mar 28 '19 at 18:42
  • @OamarKanji Jackson is a well-known JSON library for Java: https://github.com/FasterXML/jackson – Andreas Mar 28 '19 at 18:56
  • 1
    @MS90 Seems you misread the question. Jackson is *parsing* the JSON text and mapping the number value to the string field, and OP don't want the type conversion, i.e. for the number to be converted to a string. Basically, OP wants to treat the JSON text as being invalid. – Andreas Mar 28 '19 at 18:59
  • Because the data type in your `Student` class is `String`, you can change it to `int`. – LunaticJape Mar 28 '19 at 19:03
  • 1
    @MS90 OP wants `name` to be `String`, and want to make sure that when *parsing/deserializing* JSON, the value is a JSON String, e.g. `"4567"`, not a JSON number, e.g. `4567`. Jackson converts the value from `int` to `String`, being a nice helpful library, but OP want it to fail. --- *"if he wants to deserliaze content he would not have any problem whatsoever"* OP issue is that it *doesn't* fail. OP *wants* it to a fail. OP wants it to be a problem. – Andreas Mar 28 '19 at 19:12
  • @Andreas But why did he serialized it as an int in the first place? There is no logic in this code at all. Instead of fixing what initially cause all of this mess we are adding more trouble for him sometime later. His only problem and issue is a code in serialization it in the first place. – MS90 Mar 28 '19 at 19:16
  • 2
    @MS90 Check your assumptions. OP didn't serialized it as an int. OP is parsing JSON of unknown origin, and wants **strict parsing**, so that it fails if the JSON value type is incorrect. Why did you think that JSON text was created by Jackson? To paraphrase, question just says, "I have this JSON, to be parsed into this object, and I want it to fail parsing, since the type is wrong" *("How this can behavior can **changes to throw an exception** ?")*. – Andreas Mar 28 '19 at 19:20
  • If he is parsing JSON of unknown origin then he for sure must follow the logic of the code he is about to parse. There is a reason creators of such JSON serialized that field as an int? @Andreas – MS90 Mar 28 '19 at 19:27
  • @MS90 What if OP is the "author" of the JSON schema, and some other idiot created the JSON wrong? Or OP simply implemented code matching a shared schema, and did it right, i.e. it's supposed to be a string (it is a `name` value after all). You must live in a small world if you cannot envision that sharing of data can go wrong, and that you want/need strict parsing to prevent accidental misinterpretation of data. JSON is not only a storage format, where you read/write your own data, it is also an exchange format, for sharing data between disparate systems (e.g. REST Web Service). – Andreas Mar 28 '19 at 19:30
  • Agree, but highly unlikely that he would pick some JSON for his project from some "idiot" and now he wants to enlighten the world with his logic of how to deserialize it. Anyway, even the name of the field "name" implicit that it should be of type String, not to mention all other reasons why his approach and your pursue would be wrong with all this. I live in a very small world, there is no point of telling me that, but he must know what he is doing and apparently he doesn't know. If someone 10 years ago would tell me "Go after logic in your coding" I would save myself days and days of wrong a – MS90 Mar 28 '19 at 19:38
  • approaches and implementations. @Andreas He has a chance right here and right now. Don't encourage him to go other way. – MS90 Mar 28 '19 at 19:40
  • 1
    Thanks @Andreas for all the clarifications. It's detail out the need. Above JSON schema is a part of REST API exposed to a client. In the API (Swagger) 'name' parameter marked as String. But now client sending int for it and asking from our side (from API) to fail. – era Mar 29 '19 at 04:40
  • 2
    There is similar bug on [GitHub](https://github.com/FasterXML/jackson-databind/issues/796) where you can find solution with default deserialiser. – Michał Ziober Mar 29 '19 at 12:46

2 Answers2

4

Custom deserializer registered for java.lang.String should definitely work and let you prevent conversion. Deserializers will directly see content via JsonParser so they can detect underlying token type.

This will help you:

public class ForceStringDeserializer extends JsonDeserializer<String> {

    @Override
    public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        if (jsonParser.getCurrentToken() == JsonToken.VALUE_NUMBER_INT) {
            throw deserializationContext.wrongTokenException(jsonParser, JsonToken.VALUE_STRING, "Attempted to parse int to string but this is forbidden");
        }
        return jsonParser.getValueAsString();
    }
}

You can find more info here.

Mohsen
  • 4,536
  • 2
  • 27
  • 49
  • @MS90 would you please clarify more? Because I think this is exacly what OP needs! – Mohsen Mar 28 '19 at 19:02
  • What I wanted to say is that this has no logic in code at all. Your answer is correct and is per OP request, but his logic in deserializing name to int is out of any Q. for me. What happens if he has "example" instead of a number for name? @Spara – MS90 Mar 28 '19 at 19:06
  • @MS90 Aha, I got what you mean and you are correct. I hope this answer helps OP and he knows what he is doing! – Mohsen Mar 28 '19 at 19:12
  • @MS90 if user inputs are any other type except String then exception should throw. ex: following should fail (name: 4567, name: 45.678, name : true) In simple term if anything not with double quotes it need to fail – era Mar 29 '19 at 04:47
  • If you found this solution on [GitHub](https://github.com/FasterXML/jackson-databind/issues/796) you could at least add link to it. It contains very useful discussion which could be helpful. – Michał Ziober Mar 29 '19 at 12:47
0

add to application.properties

spring.jackson.mapper.allow-coercion-of-scalars=false

or if you configure object maper like bean

objectMapper.configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false);
useless9276
  • 29
  • 1
  • 8