จะบอกแจ็คสันไม่ให้รวมข้อมูลประเภทคอลเลกชันได้อย่างไร

ฉันพบ "ปัญหาการดีซีเรียลไลเซชันแบบ Polymorphic" ดังนั้นฉันจึงกำหนดค่าแจ็คสันให้เพิ่มข้อมูลประเภทสำหรับคลาสที่ไม่เป็นรูปธรรมเป็นคุณสมบัติดังต่อไปนี้:

ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
mapper.setVisibilityChecker(mapper.getSerializationConfig().getDefaultVisibilityChecker()
        .withFieldVisibility(JsonAutoDetect.Visibility.NONE)
        .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
        .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
        .withCreatorVisibility(JsonAutoDetect.Visibility.NONE)
        .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE))
mapper.enableDefaultTypingAsProperty(DefaultTyping.NON_CONCRETE_AND_ARRAYS, "__class__")

มันทำงานได้ดี แต่สำหรับอินสแตนซ์คอลเลกชัน (เช่น รายการ) จะสร้างอาร์เรย์สององค์ประกอบโดยตำแหน่งแรกเก็บสตริงที่มีข้อมูลประเภทของคอลเลกชัน (java.util.ArrayList)

สิ่งนี้ส่งผลต่อโครงสร้างของ json ที่ไคลเอนต์ (Javascript) คาดหวัง เนื่องจากตำแหน่งที่คาดว่าจะมีอาร์เรย์ ขณะนี้มีอาร์เรย์ที่มีอีกอาร์เรย์อยู่ข้างในในตำแหน่งที่สอง

ฉันหวังว่าข้อมูลประเภทการแทรกของ Jackson สำหรับประเภทที่ไม่ใช่คอลเลกชันไม่ใช่ประเภทที่เป็นรูปธรรมเท่านั้น เนื่องจากตัวเฟรมเวิร์กเองไม่ต้องการประเภทการดำเนินการรวบรวมเพื่อทำการดีซีเรียลไลซ์คุณสมบัติการรวบรวมอย่างถูกต้อง

เป็นไปได้ในลักษณะที่กำหนดค่าได้หรือไม่?


person MV Gagliotti    schedule 11.09.2014    source แหล่งที่มา


คำตอบ (1)


คุณสามารถสร้าง ObjectMapper.DefaultTypeResolverBuilder เวอร์ชันที่กำหนดเองและแทนที่เมธอด useForType() ได้

นี่คือการนำวิธีการเริ่มต้นไปใช้:

    public boolean useForType(JavaType t)
    {
        switch (_appliesFor) {
        case NON_CONCRETE_AND_ARRAYS:
            while (t.isArrayType()) {
                t = t.getContentType();
            }
            // fall through
        case OBJECT_AND_NON_CONCRETE:
            return (t.getRawClass() == Object.class) || !t.isConcrete();
        case NON_FINAL:
            while (t.isArrayType()) {
                t = t.getContentType();
            }
            return !t.isFinal(); // includes Object.class
        default:
        //case JAVA_LANG_OBJECT:
            return (t.getRawClass() == Object.class);
        }
    }

ในเวอร์ชันของคุณ เพียงเพิ่มเงื่อนไขเบื้องต้นนี้

if (t.isCollectionLikeType()) {
    return false;
}

เพื่อบอกแจ็กสันให้ข้ามประเภทที่เหมือนคอลเลกชันเพื่อแทรกข้อมูลประเภท

และตั้งค่า TypeResolverBuilder ใหม่ของคุณด้วย ObjectMapper.setDefaultTyping(myCustomTyper);

person scip    schedule 24.04.2015