programing

모든 문자열 속성에서 선행/추적 공백을 잘라내도록 잭슨을 구성할 수 있습니까?

showcode 2023. 4. 5. 22:29
반응형

모든 문자열 속성에서 선행/추적 공백을 잘라내도록 잭슨을 구성할 수 있습니까?

예 JSON(문자열에는 후행 공백이 있는 것에 주의해 주세요).

{ "aNumber": 0, "aString": "string   " }

이상적으로는 역직렬화된 인스턴스는 값이 "string"인 aString 속성(후행 공백 없음)을 가집니다.이것은 서포트되고 있는 것처럼 보이지만, 찾을 수 없습니다(Deserialization Config 등).기능).

Spring MVC 3.x를 사용하고 있기 때문에 Spring 기반 솔루션도 괜찮습니다.

포럼 투고에서 제안된 내용에 따라 Spring의 WebDataBinder를 설정하려고 했지만 Jackson 메시지컨버터를 사용하면 작동하지 않는 것 같습니다.

@InitBinder
public void initBinder( WebDataBinder binder )
{
    binder.registerCustomEditor( String.class, new StringTrimmerEditor( " \t\r\n\f", true ) );
}

Spring Boot 사용자를 위한 간단한 솔루션.walv의 Simple Module 확장을 어플리케이션 컨텍스트에 추가하기만 하면 됩니다.

package com.example;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class StringTrimModule extends SimpleModule {

    public StringTrimModule() {
        addDeserializer(String.class, new StdScalarDeserializer<String>(String.class) {
            @Override
            public String deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException,
                    JsonProcessingException {
                return jsonParser.getValueAsString().trim();
            }
        });
    }
}

잭슨을 커스터마이즈하는 또 다른 방법은 com.fasterxml.jackson.databind 유형의 콩을 추가하는 것입니다.컨텍스트에 맞게 모듈을 지정합니다.오브젝트 맵퍼 타입의 모든 빈에 등록되므로 어플리케이션에 새로운 기능을 추가할 때 커스텀모듈을 제공하는 글로벌메커니즘이 제공됩니다.

http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper

스프링 부트를 사용하지 않을 경우 StringTrimModule을 직접 등록해야 합니다(@Component에서 주석을 달 필요는 없습니다).

<bean class="org.springframework.http.converter.json.Jackson2Objec‌​tMapperFactoryBean">
    <property name="modulesToInstall" value="com.example.StringTrimModule"/>
</bean

커스텀 디시리얼라이저를 사용하면, 다음의 조작을 실시할 수 있습니다.

 <your bean>
 @JsonDeserialize(using=WhiteSpaceRemovalSerializer.class)
 public void setAString(String aString) {
    // body
 }

 <somewhere>
 public class WhiteSpaceRemovalDeserializer extends JsonDeserializer<String> {
     @Override
     public String deserialize(JsonParser jp, DeserializationContext ctxt) {
         // This is where you can deserialize your value the way you want.
         // Don't know if the following expression is correct, this is just an idea.
         return jp.getCurrentToken().asText().trim();
     }
 }

이 솔루션은 이 bean Atribute가 항상 이 방법으로 시리얼화됨을 의미하며, 이 방법으로 역직렬화하는 모든 Atribute에 주석을 달아야 합니다.

디폴트 StringDeserializer는 서드파티 라이브러리에서 사용할 수 있는 특정 케이스(여기와 여기참조)를 이미 처리하고 있으므로 이를 확장하는 것이 좋다고 생각합니다.아래에 Spring Boot 설정을 나타냅니다.이것은 2.9.0 버전 StringDeserializer에서 시작하는 것이 최종 버전이 아니기 때문에 Jackson 2.9.0 이후에서만 가능합니다.Jackson 버전이 2.9.0 이하인 경우에도 StringDeserializer의 콘텐츠를 코드에 복사하여 위의 사례를 처리할 수 있습니다.

@JsonComponent
public class StringDeserializer extends com.fasterxml.jackson.databind.deser.std.StringDeserializer {

    @Override
    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String value = super.deserialize(p, ctxt);
        return value != null ? value.trim() : null;
    }
}

주석 @JsonDeserialize의 문제는 주석 @JsonDeserialize를 항상 세터에 배치해야 한다는 것입니다.Spring MVC를 사용하여 글로벌하게 "한 번 그리고 영원히" 만들기 위해 다음 단계를 수행했습니다.

pom.xml:

<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
   <version>2.3.3</version>
</dependency>

사용자 지정 ObjectMapper 만들기:

package com.mycompany;

    import java.io.IOException;
    import org.apache.commons.lang3.StringUtils;
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
    import com.fasterxml.jackson.databind.module.SimpleModule;

    public class MyObjectMapper extends ObjectMapper {

        public MyObjectMapper() {
            registerModule(new MyModule());
        }
    }

    class MyModule extends SimpleModule {

        public MyModule() {
            addDeserializer(String.class, new StdScalarDeserializer<String>  (String.class) {
                @Override
                public String deserialize(JsonParser jp, DeserializationContext  ctxt) throws IOException,
                    JsonProcessingException {
                    return StringUtils.trim(jp.getValueAsString());
                }
            });
        }
    }

스프링의 servlet-context.xml 업데이트:

<bean id="objectMapper" class="com.mycompany.MyObjectMapper" />

    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper" ref="objectMapper" />
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

Spring Boot의 경우 매뉴얼에 기재되어 있는 커스텀디시리얼라이저를 작성하기만 하면 됩니다.

다음은 나의 그루비 코드지만 자바에서 작동하도록 자유롭게 조정하세요.

import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import org.springframework.boot.jackson.JsonComponent

import static com.fasterxml.jackson.core.JsonToken.VALUE_STRING

@JsonComponent
class TrimmingJsonDeserializer extends JsonDeserializer<String> {

    @Override
    String deserialize(JsonParser parser, DeserializationContext context) {
        parser.hasToken(VALUE_STRING) ? parser.text?.trim() : null
    }
}

com.sysml.dataformat

pom.xml

   <dependency>
      <groupId>com.fasterxml.jackson.dataformat</groupId>
      <artifactId>jackson-dataformat-csv</artifactId>
      <version>2.5.3</version>
    </dependency>

CsvUtil.java

     CsvSchema bootstrapSchema = CsvSchema.emptySchema().withHeader().sortedBy();
     CsvMapper mapper = new CsvMapper();
     mapper.enable(CsvParser.Feature.TRIM_SPACES);
     InputStream inputStream = ResourceUtils.getURL(fileName).openStream();
     MappingIterator<T> readValues =
          mapper.readerFor(type).with(bootstrapSchema).readValues(inputStream);

다음을 제안합니다.

먼저 트리밍할 모듈을 만들고 클래스에 넣습니다.

import java.io.IOException;

import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;

@Component
public class StringTrimModule extends SimpleModule {

    public StringTrimModule() {
        addDeserializer(String.class, new StdScalarDeserializer<String>(String.class) {
            @Override
            public String deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException {
                return jsonParser.getValueAsString().trim();
            }
        });
    }
}

그런 다음 클래스를 생성하여 Jackson을 설정하고 모듈을 추가합니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Class used to configure Jackson
 */
@Configuration
public class JacksonConfiguration {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new StringTrimModule());
        return mapper;
    }
}

바로 그겁니다.

언급URL : https://stackoverflow.com/questions/6852213/can-jackson-be-configured-to-trim-leading-trailing-whitespace-from-all-string-pr

반응형