Jackson JSON Processor
  1. Jackson JSON Processor
  2. JACKSON-596

Allow Forced Deserialization Of Anything To String

    Details

    • Type: New Feature New Feature
    • Status: Open Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Deserializer
    • Labels:
      None
    • Number of attachments :
      0

      Description

      Jackson deserializes any primitive JSON value to a String, if requested to do so. (By default, a JSON null value is deserialized to a null reference, even if a String were requested.)

      Similar functionality for JSON arrays and objects to be forced to String types using the databinding API is not currently available.

      Jackson should be enhanced to provide functionality to allow the user to accept any arbitrary JSON structure as a String. One possible mechanism for the user to specify that such processing is desired could be as a DeserializationConfig Feature. The following code demonstrates use of such a feature, as well as some of the current relevant behavior.

      ObjectMapper mapper = new ObjectMapper();
      
      String json1 = "1";
      System.out.println(mapper.readValue(json1, String.class));
      
      String json2 = "true";
      System.out.println(mapper.readValue(json2, String.class));
      
      String json3 = "null";
      String result3 = mapper.readValue(json3, String.class);
      System.out.println(result3);
      System.out.println(result3 == null); // true
      
      // input: {"one":1}
      String json4 = "{\"one\":1}";
      // throws JsonMappingException, complaining: 
      // Can not deserialize instance of java.lang.String 
      // out of START_OBJECT token
      // System.out.println(mapper.readValue(json4, String.class));
      // prefer a String with value {"one":1}
      
      String json5 = "[42]";
      // throws JsonMappingException, complaining: 
      // Can not deserialize instance of java.lang.String 
      // out of START_ARRAY token
      // System.out.println(mapper.readValue(json5, String.class));
      // prefer a String with value [42]
      
      mapper.configure(DeserializationConfig.Feature.ACCEPT_ALL_AS_STRING, true);
      
      System.out.println(mapper.readValue(json4, String.class));
      // output: {"one":1}
      System.out.println(mapper.readValue(json4, String.class).length());
      // output: 9
      
      System.out.println(mapper.readValue(json5, String.class));
      // output: [42]
      System.out.println(mapper.readValue(json5, String.class).length());
      // output: 4
      
      // To explain with demonstration that this feature request is not just for root level processing...
      
      // input: {"one":1,"two":{"three":"3","four":false}}
      String json6 = "{\"one\":1,\"two\":{\"three\":\"3\",\"four\":false}}";
      Example6 ex6 = mapper.readValue(json6, Example6.class);
      System.out.println(ex6);
      // output: {one:1, two:{"three":"3","four":false}}

      For per-field configurability of this feature, an annotation should also be introduced to turn the functionality on or off. If the ObjectMapper were configured with DeserializationConfig.Feature.ACCEPT_ALL_AS_STRING as false, then the annotation could turn it on for a particular field. If the ObjectMapper were configured with DeserializationConfig.Feature.ACCEPT_ALL_AS_STRING as true, then the annotation could turn it off for a particular field.

      For even greater configurability, similar class level annotation processing should be introduced.

        Activity

        Hide
        Tatu Saloranta added a comment -

        What would be use case for such a feature? As in, not just what it means, but why is useful or necessary?
        I could see it being useful either for diagnostics (print something useful for logging), or for "raw" pass-through, in which case String would need to be compliant JSON (i.e. can be parsed again, if necessary).

        For what it is worth, currently it is possible to bind any JSON to Object (with 'natural' mapping to basic JDK types), or JsonNode; and latter can be easily serialized to a String.

        I think this would be quite easy to support in some form but I want to understand what the goal is.

        Show
        Tatu Saloranta added a comment - What would be use case for such a feature? As in, not just what it means, but why is useful or necessary? I could see it being useful either for diagnostics (print something useful for logging), or for "raw" pass-through, in which case String would need to be compliant JSON (i.e. can be parsed again, if necessary). For what it is worth, currently it is possible to bind any JSON to Object (with 'natural' mapping to basic JDK types), or JsonNode; and latter can be easily serialized to a String. I think this would be quite easy to support in some form but I want to understand what the goal is.
        Hide
        Earl Baugh added a comment -

        I could use this in cases where I'm receiving input from both the web and programs, and I'd like to do some verification before I turn into objects (right now if the web is a little off, it doesn't match and goes away...) Would provide some flexibility on some of these interfaces...

        (and I didn't even think up this idea )

        Show
        Earl Baugh added a comment - I could use this in cases where I'm receiving input from both the web and programs, and I'd like to do some verification before I turn into objects (right now if the web is a little off, it doesn't match and goes away...) Would provide some flexibility on some of these interfaces... (and I didn't even think up this idea )
        Hide
        Programmer Bruce added a comment - - edited

        bhilstrom from Minnesota once wanted a feature like this. http://stackoverflow.com/questions/4783421/how-can-i-include-raw-json-in-an-object-using-jackson

        I looks like the use case may have been to provide a service that processed part of the input, and allowed another part of the input to be passed through to a different component for additional processing, allowing for separation of concerns amongst components.

        Would then a similarly useful feature be to ACCEPT_ALL_AS_BYTES?

        Show
        Programmer Bruce added a comment - - edited bhilstrom from Minnesota once wanted a feature like this. http://stackoverflow.com/questions/4783421/how-can-i-include-raw-json-in-an-object-using-jackson I looks like the use case may have been to provide a service that processed part of the input, and allowed another part of the input to be passed through to a different component for additional processing, allowing for separation of concerns amongst components. Would then a similarly useful feature be to ACCEPT_ALL_AS_BYTES?
        Hide
        Tatu Saloranta added a comment -

        Right. There is no way for Jackson to pass "raw" input without processing – this is strict limitation by implementation; and sometimes unfortunate for error reporting (where having exact input would be useful). This is actually thought to be handled by using location information that Jackson keeps track off (row, column, byte offset) with some cost (most parsers do not reliably track this info).

        I understand envelope/'russian doll' case, where some code handles outer parts or sub-parts, other pieces by something else. Of existing functionality I think that binding to Object(or Map)/JsonNode/TokenBuffer is the way to go.

        But if users would find it more convenient and/or familiar to get a String that is functionally equivalent to original input String, support can be added. It will then be recreated as sort of copy-through, so that it can be parsed as JSON.
        And yes, same could be done for byte[] too.

        I also realized that there must be a setting to enable such mapping, if we want this, because handling of Java String would then differ – normally value would not include double quotes or escaping; but when enabled ("BIND_TO_STRING_AS_JSON"?) those would be needed to keep handling symmetrical across all types.
        This would also apply to byte[], since currently any JSON String to bind to byte[] is assumed to be base64 encoded. Handling would then differ between modes.

        Show
        Tatu Saloranta added a comment - Right. There is no way for Jackson to pass "raw" input without processing – this is strict limitation by implementation; and sometimes unfortunate for error reporting (where having exact input would be useful). This is actually thought to be handled by using location information that Jackson keeps track off (row, column, byte offset) with some cost (most parsers do not reliably track this info). I understand envelope/'russian doll' case, where some code handles outer parts or sub-parts, other pieces by something else. Of existing functionality I think that binding to Object(or Map)/JsonNode/TokenBuffer is the way to go. But if users would find it more convenient and/or familiar to get a String that is functionally equivalent to original input String, support can be added. It will then be recreated as sort of copy-through, so that it can be parsed as JSON. And yes, same could be done for byte[] too. I also realized that there must be a setting to enable such mapping, if we want this, because handling of Java String would then differ – normally value would not include double quotes or escaping; but when enabled ("BIND_TO_STRING_AS_JSON"?) those would be needed to keep handling symmetrical across all types. This would also apply to byte[], since currently any JSON String to bind to byte[] is assumed to be base64 encoded. Handling would then differ between modes.
        Hide
        Programmer Bruce added a comment -

        kamaci at StackOverflow.com would appear to also want this feature. http://stackoverflow.com/questions/8137060/jackson-deserialize-variable-as-json-string

        Show
        Programmer Bruce added a comment - kamaci at StackOverflow.com would appear to also want this feature. http://stackoverflow.com/questions/8137060/jackson-deserialize-variable-as-json-string

          People

          • Assignee:
            Tatu Saloranta
            Reporter:
            Programmer Bruce
          • Votes:
            3 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: