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

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

是否可以在類級別為不同的數據類型配置 Jackson 自定義反序列化程序?

是否可以在類級別為不同的數據類型配置 Jackson 自定義反序列化程序?

鳳凰求蠱 2022-09-14 17:33:30
我需要反序列化一個長而復雜的json,為此我編寫了一組java類來映射數據,并且我必須為許多不同類型的字段(包括字符串,布爾,BigDecimal等)編寫自定義反序列化器。我知道我可以使用相應的自定義反序列化程序(如下所示)注釋java類中的所有字段,但是我需要注釋所有類中的幾乎所有字段。@JsonDeserialize(using = CustomBooleanJsonDeserializer.class)private boolean active;我也知道我可以在Spring默認值中注冊一個模塊(就像這里一樣),但我只想將這些自定義反序列化程序用于這些特定的類。ObjectMapper@Beanpublic Module customDeserializersModule() {    SimpleModule module = new SimpleModule();    module.addDeserializer(Boolean.class, new CustomBooleanJsonDeserializer());    // add other custom deserializers     return module;}我甚至知道我可以在中使用自定義,但我不想放棄通過 自動數據綁定的便利性,因為我必須防止其他人在沒有必要的自定義反序列化程序的情況下使用它。ObjectMapperRestController@RequestBody@RequestMapping(method = RequestMethod.POST, value = "/data")public ResponseEntity<ServerInfo> register(@RequestBody DataMapper data) {   // DataMapper is the target POJO class of the json's deserialization}簡而言之,我正在課堂上尋找這樣的東西:@JsonDeserialize(using = CustomStringJsonDeserializer.class, forType = String.class)@JsonDeserialize(using = CustomBooleanJsonDeserializer.class, forType = Boolean.class)@JsonDeserialize(using = CustomBigDecimalJsonDeserializer.class, forType = BigDecimal.class)public class DataMapper implements Serializable {    // obviously, @JsonDeserialize doesn't have a forType method}或者某種為類實現自定義反序列化器的方法,該方法定義了如何根據其數據類型反序列化每個字段(而無需注釋每個字段):DataMapper@JsonDeserialize(using = DataMapperJsonDeserializer.class)public class DataMapper implements Serializable {    // How can I implement the DataMapperJsonDeserializer with these     // characteristics? I know about the ContextualDeserializer interface,     // but I don't know how to use it without annotating each field.}或者以某種方式將模塊的效果限制為僅一個包或一組類:module.restrictedTo(/*some package or set of classes*/);// com.fasterxml.jackson.databind.Module doesn't have a restrictedTo method
查看完整描述

2 回答

?
慕運維8079593

TA貢獻1876條經驗 獲得超5個贊

您可以為類定義自定義反序列化程序(作為問題中的第二個想法),并在內部使用自己的自定義:ObjectMapper


public class DataMapperJsonDeserializer extends JsonDeserializer<DataMapper> {


    private static final ObjectMapper objectMapper = new ObjectMapper();

    private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy");


    static {

        SimpleModule module = new SimpleModule();

        module.addDeserializer(BigInteger.class, new CustomBigIntegerJsonDeserializer());

        module.addDeserializer(BigDecimal.class, new CustomBigDecimalJsonDeserializer());

        module.addDeserializer(Boolean.class, new CustomBooleanJsonDeserializer());

        module.addDeserializer(String.class, new CustomStringJsonDeserializer());

        objectMapper.registerModule(module);

        objectMapper.addMixIn(DataMapper.class, DefaultJsonDeserializer.class);

        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        objectMapper.setDateFormat(simpleDateFormat);

    }


    @Override

    public DataMapper deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {

        return objectMapper.readValue(jsonParser, DataMapper.class);

    }


    @JsonDeserialize

    private interface DefaultJsonDeserializer {

        // Reset default json deserializer

    }


}

請注意使用 Jackson 混合注釋(接口)從類中動態刪除自定義反序列化程序,從而避免堆棧溢出錯誤,否則由于 而會引發。DefaultJsonDeserializerPOJOobjectMapper.readValue(jsonParser, DataMapper.class)


然后,只需注釋類:POJO


@JsonDeserialize(using = DataMapperJsonDeserializer.class)

public class DataMapper implements Serializable {

    // It is not necessary to annotate each field with custom deserializers.

}

您甚至可以將其他類添加為 的字段,并且每種類型的自定義反序列化程序將自動應用于其字段,而無需注釋。POJODataMapper


查看完整回答
反對 回復 2022-09-14
?
qq_遁去的一_1

TA貢獻1725條經驗 獲得超8個贊

您可以嘗試將簡單模塊上下文序列化程序接口一起使用。第一個可用于包裝默認的去細節,第二個用于檢查類型配置 - 檢查注釋。

讓我們從注釋開始:

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@interface ForceCustomDeserializer {

}

我假設您只有一個給定類型的自定義實現,但如果它不是真正的,請擴展上面的注釋并提供一些額外的信息,這些信息允許使用適當的去字符。例如,下面我們可以看到兩個自定義的去序列化器,它們額外記錄一些信息并運行默認的反序列化。使用基礎去細節,因為如果您有一些額外的配置,我們不會松動它。


class CustomBoolDeserializer extends StdScalarDeserializer<Boolean> implements ContextualDeserializer {


    private NumberDeserializers.BooleanDeserializer base;


    public CustomBoolDeserializer(NumberDeserializers.BooleanDeserializer base) {

        super(Boolean.class);

        this.base = base;

    }


    @Override

    public Boolean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {

        System.out.println("Custom BooleanDeserializer ....");


        return base.deserialize(p, ctxt);

    }


    @Override

    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {

        Class<?> parent = property.getMember().getDeclaringClass();

        ForceCustomDeserializer annotation = parent.getAnnotation(ForceCustomDeserializer.class);


        return annotation == null ? base : this;

    }

}


class CustomStringDeserializer extends StringDeserializer implements ContextualDeserializer {


    private final StringDeserializer base;


    public CustomStringDeserializer(StringDeserializer base) {

        this.base = base;

    }


    @Override

    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {

        System.out.println("Custom StringDeserializer ....");


        return base.deserialize(p, ctxt);

    }


    @Override

    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {

        Class<?> parent = property.getMember().getDeclaringClass();

        ForceCustomDeserializer annotation = parent.getAnnotation(ForceCustomDeserializer.class);


        return annotation == null ? base : this;

    }

}

我們可以測試上面的自定義實現,如下所示:


import com.fasterxml.jackson.core.JsonParser;

import com.fasterxml.jackson.databind.BeanDescription;

import com.fasterxml.jackson.databind.BeanProperty;

import com.fasterxml.jackson.databind.DeserializationConfig;

import com.fasterxml.jackson.databind.DeserializationContext;

import com.fasterxml.jackson.databind.JsonDeserializer;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;

import com.fasterxml.jackson.databind.deser.ContextualDeserializer;

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

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

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

import com.fasterxml.jackson.databind.module.SimpleModule;


import java.io.File;

import java.io.IOException;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;


public class JsonApp {


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

        File jsonFile = new File("./resource/test.json").getAbsoluteFile();


        SimpleModule forcedCustomModule = new SimpleModule();

        forcedCustomModule.setDeserializerModifier(new BeanDeserializerModifier() {

            @Override

            public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {

                if (deserializer instanceof StringDeserializer) {

                    // wrap with yours or return new deserializer

                    return new CustomStringDeserializer((StringDeserializer) deserializer);

                }

                if (deserializer instanceof NumberDeserializers.BooleanDeserializer) {

                    // wrap with yours or return new deserializer

                    return new CustomBoolDeserializer((NumberDeserializers.BooleanDeserializer) deserializer);

                }

                // override for other types


                return deserializer;

            }

        });


        ObjectMapper mapper = new ObjectMapper();

        mapper.registerModule(forcedCustomModule);


        System.out.println(mapper.readValue(jsonFile, Pojo.class));

    }

}


@ForceCustomDeserializer

class Pojo {


    private String name;

    private boolean bool;


    // getters, setters, toString

}

以上示例為以下有效負載:JSON


{

  "name": "Jackson",

  "bool": true

}

指紋:


Custom StringDeserializer ....

Custom BooleanDeserializer ....

Pojo{name='Jackson', bool=true}


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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