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

How to use JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS #586

Closed
farsunset opened this issue Dec 27, 2019 · 13 comments
Closed

How to use JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS #586

farsunset opened this issue Dec 27, 2019 · 13 comments

Comments

@farsunset
Copy link

The enum JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS is Deprecated in version jackson-core 2.10.0. I see to use JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS. but i can't find api to use this. can who show a case use ObjectMapper? thanks

@cowtowncoder
Copy link
Member

Usage can be done in 3 ways:

  1. When constructing JsonFactory (needs new builder() approach)
  2. When constructing JsonMapper (subtype of ObjectMapper, needs new builder() approach)
  3. When creating ObjectReader instances

In first 2 of these, approach requires something like:

JsonFactory f = JsonFactory.builder().enable(... feature).build();
// or
JsonMapper m = JsonMapper.builder().enable(... feature).build();
// or, since `ObjectMapper` is base type, you can just use that
ObjectMapper m = JsonMapper.builder().enable(... feature).build();

Third approach might be easiest as you can use existing ObjectMapper:

ObjectReader r = mapper.readerFor(MyType.class).with(... feature...);
MyType value = r.readValue(source);

@farsunset
Copy link
Author

it is very helpful. thanks

@amreladawy
Copy link

Actually, JsonMapper m = JsonMapper.builder().enable(... feature).build(); did not work. the enable method expects a JsonParser.Feature while JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS isJsonReadFeature.

I tried this JsonMapper m = JsonMapper.builder().enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature()).build();. but it has no effect. I had to revert back to the deprecated feature.

@cowtowncoder
Copy link
Member

@amreladawy I can not reproduce this: works for me with Jackson 2.10.4, using either one of below:

        ObjectMapper MAPPER = new JsonMapper();
        Map<?, ?> result = MAPPER.readerFor(Map.class)
                .with(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS)
                .readValue(JSON);
        assertEquals(1, result.size());

        // and new mapper should work
        ObjectMapper mapper2 = JsonMapper.builder()
                .enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS)
                .build();
        result = mapper2.readerFor(Map.class)
                .readValue(JSON);

but if you can reproduce it with at test, specific Jackson version, please file an issue for jackson-databind.

cowtowncoder added a commit to FasterXML/jackson-databind that referenced this issue May 4, 2020
@amreladawy
Copy link

@cowtowncoder Thanks for coming back to me on this closed issue. Here is the code

import com.fasterxml.jackson.core.json.JsonReadFeature
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule
import org.glassfish.jersey.client.proxy.WebResourceFactory
import javax.ws.rs.client.ClientBuilder
import javax.ws.rs.ext.ContextResolver

inline fun <reified T> getApi(url: String): T = try {
        WebResourceFactory.newResource(T::class.java, ClientBuilder.newClient()
        .register(
            ContextResolver {
                ObjectMapper()
                    .enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature())
                    .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
                    .registerModule(Jdk8Module()).registerModule(ParameterNamesModule())
            }
        ).target(url))
} catch (e: Exception) {
    e.printStackTrace()
}

This is kotlin, but should not make any difference. I am using jakson 2.11.0

Here is the signature of the enable method.

    /**
     * Method for enabling specified {@link com.fasterxml.jackson.core.JsonParser.Feature}s
     * for parser instances this object mapper creates.
     *<p>
     * Note that this is equivalent to directly calling same method on {@link #getFactory}.
     *<p>
     * WARNING: since this method directly modifies state of underlying {@link JsonFactory},
     * it will change observed configuration by {@link ObjectReader}s as well -- to avoid
     * this, use {@link ObjectReader#with(JsonParser.Feature)} instead.
     *
     * @since 2.5
     */
    public ObjectMapper enable(JsonParser.Feature... features) {
        for (JsonParser.Feature f : features) {
            _jsonFactory.enable(f);
        }
        return this;
      }

There is not signature that accepts JsonReadFeature or FormatFeature

By the way, the above code worked and was able to activate the feature.

@cowtowncoder
Copy link
Member

cowtowncoder commented May 4, 2020

@amreladawy seems like you were trying to find ObjectMapper.enable(JsonReadFeature) which does not exist (correct).
What exists is JsonMapper.builder().enable(JsonReadFeature) (or ObjectReader.with(JsonReadFeature) ).
This is a bit confusing since your earlier example DID use builder approach (added in 2.10).

Deprecated variant does still work with 2.x for backwards-compatibility reasons and will not be removed until 3.0. So that is fine. It is deprecated as 3.0 will remove direct mutability of ObjectMapper (and lower level JsonFactory), so goal is to help developers migrate to new mechanism over time.

@amreladawy
Copy link

Thanks for your help on that.

@amittal1
Copy link

amittal1 commented Aug 11, 2020

I think everyone figured it out already but just adding something which bugged me for a while before finally getting the solution. I didn't want to create to custom Mapper but continue using my application.properties file. If you are using spring-boot version 1.5.18 and using the application.properties file, then you can simply add one line in your application.properties file:
spring.jackson.parser.allow-unquoted-control-chars=true

No need to create custom Mapper or anything. This resolved my issue.

@cowtowncoder
Copy link
Member

@amittal1 thank you for sharing this!

@zipper01
Copy link

zipper01 commented Feb 8, 2021

I think everyone figured it out already but just adding something which bugged me for a while before finally getting the solution. I didn't want to create to custom Mapper but continue using my application.properties file. If you are using spring-boot version 1.5.18 and using the application.properties file, then you can simply add one line in your application.properties file:
spring.jackson.parser.allow-unquoted-control-chars=true

No need to create custom Mapper or anything. This resolved my issue.

Why you asume everyone is using spring?

@adamu
Copy link

adamu commented Feb 22, 2021

I was having problems with using this via Jackson2ObjectMapperBuilderCustomizer and Jackson2ObjectMapperBuilder.featuresToEnable.

featuresToEnable accepts Objects, so replacing JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS with JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS compiles, but fails at runtime with

org.springframework.beans.FatalBeanException: Unknown feature class: com.fasterxml.jackson.core.json.JsonReadFeature

I'm not sure why, but I worked around with JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature(), which uses the same value, but avoids the deprecation warning.

@channyeintun
Copy link

@amittal1 Thank you for sharing. :D

@He-Pin
Copy link

He-Pin commented Dec 17, 2024

I'm not sure why it works when parsing the name-selector.json` in jsonpath-standard/jsonpath-compliance-test-suite#94

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

No branches or pull requests

8 participants