亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用在類字段中指定的自定義反序列化器反序列化字符串

使用在類字段中指定的自定義反序列化器反序列化字符串

米琪卡哇伊 2021-09-29 17:39:14
我需要編寫一個方法,它接受一些對象、fieldName給定對象的類中存在的一些字段名稱和一些字段值value。該值是字段的 JSON 序列化形式。該方法應取值并相應地反序列化它,如下所示:static void setField(Object obj, String fieldName, String value) throws Exception {    Field field = obj.getClass().getDeclaredField(fieldName)    Object valObj = objectMapper.readValue(value, field.getType());    field.set(obj, valObj);}(我實際上只需要檢索反序列化的值,而不是再次設置它,但這使它成為一個更好的例子。)只要 jackson 的默認反序列化就足夠了?,F在讓我們假設我有一個帶有自定義(反)序列化器的類:class SomeDTO {    String foo;    @JsonSerialize(using = CustomInstantSerializer.class)    @JsonDeserialize(using = CustomInstantDeserializer.class)    Instant bar;}一種可能的解決方案是手動檢查JsonDeserialize注釋。但是,我真的不想嘗試復制 Jackson 在決定使用哪種序列化器時遵循的任何策略,因為這看起來很脆弱(例如全局注冊的序列化器)。是否有使用 DTO 類中定義的字段反序列化配置反序列化值的好方法?也許在將字段的注釋傳遞給 Jackson 的同時將值反序列化為字段的類型,以便他們得到尊重?我設法獲得了一個AnnotatedMember實例,其中包含所有必需的信息(JSON 注釋和反射字段或 setter/getter 訪問),但無法弄清楚我將如何使用它來反序列化一個獨立的值由于缺乏文件:final JavaType dtoType = objectMapper.getTypeFactory().constructType(SomeDTO.class);final BeanDescription description = objectMapper.getDeserializationConfig().introspect(dtoType);for (BeanPropertyDefinition propDef: beanDescription.findProperties()) {    final AnnotatedMember mutator = propertyDefinition.getNonConstructorMutator();    // now what? Also: How do I filter for the correct property?}
查看完整描述

2 回答

?
繁花如伊

TA貢獻2012條經驗 獲得超12個贊

一種可能性是序列化對象,替換給定的字段,然后再次反序列化它。當序列化 from/toJsonNode而不是 JSON-String 時,這可以輕松完成,如下所示:


static Object setField(Object obj, String fieldName, String value) throws Exception {

    // note: produces a new object instead of modifying the existing one

    JsonNode node = objectMapper.valueToTree(obj);

    ((ObjectNode) node).put(fieldName, value);

    return objectMapper.readValue(node.traverse(), obj.getClass());

}

但是,僅僅為了反序列化單個字段而對整個對象進行序列化和反序列化似乎開銷很大,并且可能很脆弱,因為 DTO 類的其他方面會影響單個字段的反序列化過程


查看完整回答
反對 回復 2021-09-29
?
拉風的咖菲貓

TA貢獻1995條經驗 獲得超2個贊

import com.fasterxml.jackson.core.JsonGenerator;

import com.fasterxml.jackson.core.JsonParser;

import com.fasterxml.jackson.core.JsonProcessingException;

import com.fasterxml.jackson.databind.DeserializationContext;

import com.fasterxml.jackson.databind.DeserializationFeature;

import com.fasterxml.jackson.databind.JsonNode;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fasterxml.jackson.databind.SerializerProvider;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

import com.fasterxml.jackson.databind.ser.std.StdSerializer;


import java.io.IOException;

import java.util.Map;


public final class Jackson {


  private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()

      .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);


  public static void main(String[] args) throws IOException {

    Dto source = makeDto("Master", 31337);

    Dto dst = makeDto("Slave", 0xDEADBEEF);


    //1. read value of field "fieldName" from json source

    //2. clones destination object, sets up field "fieldName" and returns it

    //3. in case of no field either on "src" or "dst" - throws an exception

    Object result = restoreValue(dst, "details", OBJECT_MAPPER.writeValueAsString(source));

    System.out.println(result);

  }


  private static Object restoreValue(Object targetObject, String fieldName, String sourceObjectAsJson) throws IOException {

    String targetObjectAsJson = OBJECT_MAPPER.writeValueAsString(targetObject);

    Map sourceAsMap = OBJECT_MAPPER.readValue(sourceObjectAsJson, Map.class);

    Map targetAsMap = OBJECT_MAPPER.readValue(targetObjectAsJson, Map.class);

    targetAsMap.put(fieldName, sourceAsMap.get(fieldName));

    String updatedTargetAsJson = OBJECT_MAPPER.writeValueAsString(targetAsMap);

    return OBJECT_MAPPER.readValue(updatedTargetAsJson, targetObject.getClass());

  }


  private static Dto makeDto(String name, int magic) {

    Dto dto = new Dto();

    dto.setName(name);

    CustomDetails details = new CustomDetails();

    details.setMagic(magic);

    dto.setDetails(details);

    return dto;

  }


  private static final class Dto {

    private String name;

    @JsonSerialize(using = CustomDetails.CustomDetailsSerializer.class)

    @JsonDeserialize(using = CustomDetails.CustomDetailsDeserializer.class)

    private CustomDetails details;


    public String getName() {

      return name;

    }


    public void setName(String name) {

      this.name = name;

    }


    public CustomDetails getDetails() {

      return details;

    }


    public void setDetails(CustomDetails details) {

      this.details = details;

    }


    @Override

    public String toString() {

      return "Dto{" +

          "name='" + name + '\'' +

          ", details=" + details +

          '}';

    }

  }



  private static final class CustomDetails {

    private int magic;


    public int getMagic() {

      return magic;

    }


    public void setMagic(int magic) {

      this.magic = magic;

    }


    @Override

    public String toString() {

      return "CustomDetails{" +

          "magic=" + magic +

          '}';

    }


    public static final class CustomDetailsSerializer extends StdSerializer<CustomDetails> {


      public CustomDetailsSerializer() {

        this(null);

      }



      public CustomDetailsSerializer(Class<CustomDetails> t) {

        super(t);

      }


      @Override

      public void serialize(CustomDetails details, JsonGenerator jg, SerializerProvider serializerProvider) throws IOException {

        jg.writeStartObject();

        jg.writeNumberField("_custom_property_magic", details.magic);

        jg.writeEndObject();

      }

    }



    private static final class CustomDetailsDeserializer extends StdDeserializer<CustomDetails> {


      public CustomDetailsDeserializer() {

        this(null);

      }



      public CustomDetailsDeserializer(Class<CustomDetails> t) {

        super(t);

      }


      @Override

      public CustomDetails deserialize(JsonParser jp, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {

        JsonNode node = jp.getCodec().readTree(jp);

        int magic = (Integer) node.get("_custom_property_magic").numberValue();

        CustomDetails

            customDetails = new CustomDetails();

        customDetails.setMagic(magic);

        return customDetails;

      }

    }

  }

}

所以輸出是:


Dto{name='Slave', details=CustomDetails{magic=31337}}


查看完整回答
反對 回復 2021-09-29
  • 2 回答
  • 0 關注
  • 215 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號