jackson 은 null 회전 0 및 0 회전 null 의 예제 코드 를 실현 합 니 다.

9976 단어 jacksonnull0
필요 배경
최근 에 수치 형식의 필드 가 필요 하지 않 습 니 다.기본 값 은 비어 있 습 니 다.데이터베이스 바늘 은 이 필드 에 int 형식 으로 설계 되 었 습 니 다.dba 추천 규범 으로 인해 기본 값 은 not null 입 니 다.이때 문제 가 발생 했 습 니 다.데이터 베 이 스 는 기본적으로 0 이 저장 되 어 있 고 전단 전시 시 이 0 을 표시 할 수 없습니다.(필요 한 것 은 null)
해결 방안
이러한 처리 에 대해 일반적인 방안 은 다음 과 같은 두 가지 가 있다.
전단 을 처리 하고 0 과 null 을 통일 적 으로 처리 합 니 다.0 은 null 이 고 null 은 0 입 니 다.
백 엔 드 를 처리 합 니 다.처리 할 필드 에 대해 직렬 화 되 기 전이 나 그 후에 처리 하거나 하 드 인 코딩 방식 으로 처리 할 필드 에 대해 if else 를 씁 니 다.
방안 분석
첫 번 째,이 안 에는 비교적 난처 한 부분 이 있 습 니 다.전단 에 접 수 된 필드 중 일부 0 은 의미 가 있 습 니 다.예 를 들 어 효과 가 있 는 지,0 은 효과 가 있 는 지,만약 에 통일 적 으로 처리 하면 이것 은 null 로 바 뀌 면 문제 가 발생 합 니 다.만약 에 통일 적 으로 처리 하지 않 으 면 구별 해 야 한다.전단 에 대해 잘 모 르 기 때문에 주석 이나 표지 가 있 는 전체적인 방법 으로 비슷 한 문 제 를 처리 하 는 지 모 르 겠 고 전단 의 말 을 들 으 면 처리 가 비교적 번거롭다.so 는 백 엔 드 에서 만 처리 할 수 있다.
두 번 째,백 엔 드 처리 방식 이 더욱 유연 합 니 다.간단하게 확장 하려 면@Jason Serialize 와@Json Deserialize 주 해 를 사용 하여 사용자 정의 직렬 화 와 반 직렬 화 류 를 작성 하 십시오.빨리 완성 하려 면 하 드 인 코딩 을 하 세 요.처음에 잭 슨 의 직렬 화 반 직렬 화 체제 에 대해 잘 몰 랐 기 때문에 2 개의 serializer 와 deserializer 를 발표 한 후에 도 문제 가 끊 이지 않 았 기 때문에 프로젝트 의 진전 을 확보 하기 위해 비교적 역 겨 운 하 드 코딩 방식 으로 if else 를 많이 써 서 판단 했다.
테스트 직렬 화
maven 의존:jackson 버 전 2.9.7

 <dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-databind</artifactId>
 <version>${jackson.version}</version>
 </dependency>
 <dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-core</artifactId>
 <version>${jackson.version}</version>
 </dependency>
 <dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-annotations</artifactId>
 <version>${jackson.version}</version>
 </dependency>
직렬 화 클래스:

 @JacksonStdImpl
public class ZeroToNullSerializer extends JsonSerializer implements ContextualSerializer {

 private Class<?> type;

 public ZeroToNullSerializer() {

 }

 public ZeroToNullSerializer(final JavaType type) {
  this.type = type == null ? Object.class : type.getRawClass();
 }

 @Override
 public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

  if (o instanceof Short) {
   if (((Short) o).compareTo((short)0) == 0) {
    jsonGenerator.writeNull();
   } else {
    jsonGenerator.writeNumber(((Short) o).shortValue());
   }
  }
  if (o instanceof Integer) {
   if (((Integer) o).intValue() == 0) {
    jsonGenerator.writeNull();
   } else {
    jsonGenerator.writeNumber(((Integer) o).intValue());
   }
  }
  if (o instanceof Float) {
   if (((Float) o).compareTo(0f) == 0) {
    jsonGenerator.writeNull();
   } else {
    jsonGenerator.writeNumber(((Float) o).floatValue());
   }
  }

  if (o instanceof Double) {
   if (((Double) o).compareTo(0D) == 0) {
    jsonGenerator.writeNull();
   } else {
    jsonGenerator.writeNumber(((Double) o).doubleValue());
   }
  }

  if (o instanceof Long) {
   if (((Long) o).compareTo(0L) == 0) {
    jsonGenerator.writeNull();
   } else {
    jsonGenerator.writeNumber(((Long) o).longValue());
   }
  }
  if (o instanceof BigDecimal) {
   if (((BigDecimal) o).compareTo(BigDecimal.ZERO) == 0) {
    jsonGenerator.writeNull();
   }else {
    jsonGenerator.writeNumber((BigDecimal) o);
   }
  }
 }

 @Override
 public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
  return new ZeroToNullSerializer(property.getType());
 }
}
테스트 서열 화 된 bean:

@Data
public class TestSerializerBean {
 @JsonSerialize(using =ZeroToNullSerializer.class)
 private Integer number;
 private Integer age;
 private BigDecimal money;
}
직렬 화 테스트:

@Test
 public void testSerializer() throws JsonProcessingException {
 TestSerializerBean serializerBean = new TestSerializerBean();
 serializerBean.setNumber(0);
 serializerBean.setAge(0);
 serializerBean.setMoney(new BigDecimal(20));

 String string = mapper.writeValueAsString(serializerBean);

 System.out.println(string);
 }

테스트 결과:
1.테스트 대기 필드 테이프 0:

2.테스트 대기 필드 0 없 음

@Test
 public void testSerializer() throws JsonProcessingException {
 TestSerializerBean serializerBean = new TestSerializerBean();
 serializerBean.setNumber(10);
 serializerBean.setAge(0);
 serializerBean.setMoney(new BigDecimal(20));

 String string = mapper.writeValueAsString(serializerBean);

 System.out.println(string);
 }

테스트 역 직렬 화
역 직렬 화 클래스(핵심 코드 만 붙 이 고 전체 코드 는 github 에 업로드 합 니 다.주 소 는 뒷글 링크 참조):

 @Override
 public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
  if (this.type == Integer.class) {
   return handleInteger(p, ctxt);
  }
  if (this.type == Long.class) {
   return handleLong(p, ctxt);
  }
  if (this.type == BigDecimal.class) {
   return handleBigDecimal(p, ctxt);
  }
  if (this.type == Double.class) {
   return handleDouble(p, ctxt);
  }
  if (this.type == Float.class) {
   return handleFloat(p, ctxt);
  }
  if (this.type == Short.class) {
   return handleShort(p, ctxt);
  }
  throw new RuntimeException("      ,  " + type.toString() + "+            ");
 }

private Object handleBigDecimal(JsonParser p, DeserializationContext ctxt) throws IOException {
  switch (p.getCurrentTokenId()) {
   case JsonTokenId.ID_NUMBER_INT:
   case JsonTokenId.ID_NUMBER_FLOAT:
    return p.getDecimalValue();
   case JsonTokenId.ID_STRING:
    String text = p.getText().trim();
    // note: no need to call `coerce` as this is never primitive
    if (text == null || text.length() == 0) {
     return getNullValue(ctxt);
    }
    try {
     return new BigDecimal(text);
    } catch (IllegalArgumentException iae) {
    }
    return (BigDecimal) ctxt.handleWeirdStringValue(type, text,
      "not a valid representation");
   case JsonTokenId.ID_START_ARRAY:
    throw new RuntimeException("NullToZeroDeserializer handleBigDecimal error, encounter token " + JsonTokenId.ID_START_ARRAY);
  }
  // Otherwise, no can do:
  return (BigDecimal) ctxt.handleUnexpectedToken(type, p);
 }
 
  @Override
 public Object getNullValue(DeserializationContext ctxt) throws JsonMappingException {
  if (this.type == Integer.class) {
   return 0;
  }
  if (this.type == BigDecimal.class) {
   return BigDecimal.ZERO;
  }
  return 0;
 }
역 정렬 을 기다 리 는 bean:

@Data
public class TestDeSerializerBean{
 private Integer number;
 @JsonDeserialize(using = NullToZeroDeserializer.class)
 private BigDecimal money;
 private BigDecimal balance;
}
역 직렬 화 테스트:

@Test
 public void testDeSerializer() throws IOException {
 TestDeSerializerBean serializerBean = new TestDeSerializerBean();
 serializerBean.setNumber(5);
 serializerBean.setMoney(new BigDecimal(20));

 String string = mapper.writeValueAsString(serializerBean);

 String testStr = "{
" + " \"number\": 5,
" + " \"money\": \"20.0\"
" + "}"; TestDeSerializerBean deSerializerBean = mapper.readValue(testStr, TestDeSerializerBean.class); System.out.println(deSerializerBean); }
테스트 결과:
null 형식:

@Test
 public void testDeSerializer() throws IOException {
 TestDeSerializerBean serializerBean = new TestDeSerializerBean();
 serializerBean.setNumber(5);
 serializerBean.setMoney(new BigDecimal(20));

 String string = mapper.writeValueAsString(serializerBean);

 String testStr = "{
" + " \"number\": 5,
" + " \"money\": \"\"
" + "}"; TestDeSerializerBean deSerializerBean = mapper.readValue(testStr, TestDeSerializerBean.class); System.out.println(deSerializerBean); }

2.비 null 형식

역 직렬 화 된 클래스 직렬 화 null 값 을 사용 할 때 getNullValue 방법 을 다시 쓰 는 것 에 주의 하 십시오.
총결산
이상 은 null 에서 0 으로 전환 하고 0 으로 전환 하 는 null 에 대한 코드 일 뿐 사용자 정의 직렬 화가 필요 할 때 기 존의 serializer 와 deserializer 류 를 참고 할 수 있 습 니 다.예 를 들 어 DateDeserializer 와 DateSerializer,BigDecimal Deserializer 와 BigDecimal Serializer 등 입 니 다.이러한 이후 의 직렬 화 와 반 직렬 화 류 를 참고 하여 우 리 는 원 하 는 사용자 정의 직렬 화 와 반 직렬 화 효 과 를 쓸 수 있다.
코드 주소
이상 의 이 jackson 은 null 전 0 과 0 전 null 을 실현 하 는 예제 코드 는 바로 작은 편집 이 여러분 에 게 공유 하 는 모든 내용 입 니 다.참고 하 시기 바 랍 니 다.여러분 들 도 저 희 를 많이 사랑 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기