วิธีระบุแจ็คสันให้ใช้เฉพาะฟิลด์ต่างๆ


191

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

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

ฉันสามารถทำสิ่งนี้ในแต่ละชั้นเรียนพร้อมคำอธิบายประกอบ:

 @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)

แต่ฉันไม่ต้องการที่จะใส่มันในทุก ๆ ชั้น ...

เป็นไปได้ไหมที่จะกำหนดค่านี้ทั่วโลก? ชอบเพิ่มบางอย่างใน Object Mapper หรือไม่


1
ทิมให้คำตอบที่ดี ความเป็นไปได้อีกอย่างก็คือถ้าคุณมีคลาสพื้นฐานร่วมกันคุณสามารถใส่คำอธิบายประกอบในคลาสนั้นได้ คำอธิบายประกอบได้รับการถ่ายทอดโดยแจ็คสัน
StaxMan

1
ฉันคิดว่าฉันลองมัน แต่ดูเหมือนว่าคุณต้องบอกคลาสย่อยให้ใช้สิ่งที่เคสพื้นฐานกำหนด ...
Michael Wiles

2
ไม่เว้นแต่จะมีการแทนที่คำอธิบายประกอบของคลาสย่อยการเพิ่มความคิดเห็นของผู้ปกครองจะสามารถมองเห็นได้ราวกับว่าพวกเขาเป็นส่วนหนึ่งของคำจำกัดความของคลาสย่อย (หากไม่ใช่จะเป็นข้อผิดพลาด) นี่ไม่ใช่วิธีที่ JDK เกี่ยวข้องกับการเพิ่มความคิดเห็น แต่ Jackson ใช้การสืบทอดแบบเต็มสำหรับการเพิ่มความคิดเห็น (แม้สำหรับการเพิ่มความคิดเห็นด้วยวิธี)
StaxMan

ระวังINFER_PROPERTY_MUTATORSธง มันบังคับให้มองเห็นของ setters หากมีทะเยอทะยานหรือมองเห็นได้
Ondra Žižka

และคนอื่น ๆ
Ondra Žižka

คำตอบ:


157

คุณสามารถกำหนดค่า ObjectMappers แต่ละรายการดังนี้:

ObjectMapper mapper  = new ObjectMapper();
mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
                .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));

หากคุณต้องการให้มันตั้งค่าทั่วโลกฉันมักจะเข้าถึง mapper ที่กำหนดค่าผ่านคลาส wrapper


3
ดีแม้ว่าฉันคิดว่าคุณอาจต้องตั้งค่าตัวตรวจสอบ (withXxx () วิธีการมักจะสร้างวัตถุใหม่) ดังนั้นบางอย่างเช่น 'mapper.setVisibilityChecker (mapper.getVisibilityChecker (). กับ ... );'
StaxMan

@StaxMan โทรดีใน setVisibilityChecker ฉันแก้ไขคำตอบเพื่อสะท้อน
Kevin Bowersox

42
withGetterVisibilityไม่ครอบคลุมis*วิธีการ แต่มีwithIsGetterVisibilityสำหรับพวกเขา
qerub

13
setVisibilityCheckerเลิกใช้แล้ว ใช้setVisibilityแทน
0x7d7b

1
นี่คือสิ่งที่ฉันต้องการ! การกำหนดค่านี้อนุญาตให้ฉันใช้ Mixin เพื่อแปลง Hibernate entity เป็น DTO ได้อย่างง่ายดาย โดยค่าเริ่มต้น ObjectMapper ทุกอย่างเป็นอนุกรมและ Mixin จะต้องระบุคุณสมบัติที่จะละเว้น (เช่นการลบแทนการแยก)
TastyWheat

150

ใน Jackson 2.0 และใหม่กว่าคุณสามารถใช้:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;   

...

ObjectMapper mapper = new ObjectMapper();    
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

เพื่อปิดการตรวจหาอัตโนมัติ


1
สวัสดีพวกฉันใช้กระปุก 1.9.0 ของแจ็คสัน ฉันได้รับคุณสมบัติ json เพิ่มเติมในขณะที่วัตถุเป็นอนุกรมสตริง JSON ฉันต้องการรับสตริง json ซึ่งมีตัวแปรที่กล่าวถึงด้วย @JsonProperty เท่านั้น คุณช่วยฉันเรื่องนี้ได้ไหม
jrhamza

7
คุณสามารถเริ่มต้นด้วยคำอธิบายประกอบชั้นที่กล่าวถึงในคำถาม OP: @JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)ถัดไปคุณต้องใส่คำอธิบายประกอบแต่ละคุณสมบัติที่คุณต้องการรวมด้วย@JsonProperty
lukk

ขอบคุณ! ก่อนหน้านี้ฉันพบตัวอย่างโค้ดจำนวนมากที่มีการอ้างอิง JsonMethod แทนที่จะเป็น PropertyAccessor หากคุณค้นหา JsonMethod คุณจะไม่ค่อยได้รับลิงก์ไปยัง PropertyAccessor ดังนั้น ... วิธีที่ดีที่สุดในการค้นหาชื่อคลาสที่ถูกแทนที่ในสิ่งที่จะทำต่อคืออะไร? สามารถแกร่งและน่ารังเกียจใช่ไหม?
philburns

38

โดยเฉพาะสำหรับผู้ได้รับboolean is*():

ฉันใช้เวลามากมายกับสาเหตุที่ไม่ได้อยู่ข้างล่างนี้

  @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)

หรือสิ่งนี้

  setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE);
  setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);
  setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

ทำงานให้กับ Boolean Getter / Setter ของฉัน

โซลูชันนั้นง่าย:

  @JsonAutoDetect(isGetterVisibility = Visibility.NONE, ...          
  setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);

อัปเดต: สปริงบูตอนุญาตให้กำหนดค่า:

jackson:
  visibility.field: any
  visibility.getter: none
  visibility.setter: none
  visibility.is-getter: none

ดูคุณสมบัติของแอ็พพลิเคชันทั่วไป # JACKSON


1
คุณช่วยอธิบายวิธีการแก้ปัญหาง่ายๆที่ควรนำไปใช้กับคลาสของถั่วได้หรือไม่
Pavel Niedoba

1
ขอบคุณ. นั่นคือ Getter บันทึกวันสำหรับฉัน
grinch

นี่ไม่ใช่คำตอบสำหรับคำถามและค่อนข้างทำให้เข้าใจผิด
Ondra Žižka

14

สำหรับ jackson 1.9.10 ฉันใช้

ObjectMapper mapper = new ObjectMapper();

mapper.setVisibility(JsonMethod.ALL, Visibility.NONE);
mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);

เพื่อเปิดการอุทิศอัตโนมัติ


2
นั่นคือวิธีการ ขอบคุณ
cuneytykaya

สงสัยว่ามีความแตกต่างระหว่างการทำเช่นนี้กับการปิดใช้งาน "การตรวจจับอัตโนมัติ" หรือไม่
xenoterracide

10

เกี่ยวกับสิ่งนี้: ฉันใช้กับ mixin

วัตถุที่ไม่เข้ากัน

@Entity
@Getter
@NoArgsConstructor
public class Telemetry {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long pk;
    private String id;
    private String organizationId;
    private String baseType;
    private String name;
    private Double lat;
    private Double lon;
    private Instant updateTimestamp;
}

mixin:

@JsonAutoDetect(fieldVisibility = ANY, getterVisibility = NONE, setterVisibility = NONE)
public static class TelemetryMixin {}

การใช้งาน:

    ObjectMapper om = objectMapper.addMixIn(Telemetry.class, TelemetryMixin.class);
    Telemetry[] telemetries = om.readValue(someJson, Telemetry[].class);

ไม่มีอะไรที่บอกว่าคุณไม่สามารถระบุจำนวนชั้นเรียนและใช้มิกซ์อินเดียวกันได้

หากคุณไม่คุ้นเคยกับมิกซ์อินพวกเขามีแนวคิดง่าย ๆ : โครงสร้างมิกซ์อินนั้นถูกกำหนดไว้อย่างดีเยี่ยมในกลุ่มเป้าหมาย


3

หากคุณต้องการวิธีการทำสิ่งนี้ทั่วโลกโดยไม่ต้องกังวลกับการกำหนดค่าของคุณObjectMapperคุณสามารถสร้างคำอธิบายประกอบของคุณเอง:

@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonAutoDetect(
        getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE,
        setterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.NONE,
        creatorVisibility = JsonAutoDetect.Visibility.NONE
)
public @interface JsonExplicit {
}

ตอนนี้คุณเพียงแค่ต้องใส่คำอธิบายประกอบการเรียนของคุณด้วย@JsonExplicitและคุณความดีกำลังจะไป!

นอกจากนี้ตรวจสอบให้แน่ใจว่าได้แก้ไขการโทรด้านบน@JsonAutoDetectเพื่อให้แน่ใจว่าคุณได้ตั้งค่าเป็นสิ่งที่ทำงานกับโปรแกรมของคุณ

ให้เครดิตกับhttps://stackoverflow.com/a/13408807เพื่อช่วยฉันค้นหาข้อมูล@JacksonAnnotationsInside


3

หากคุณใช้ Spring Boot คุณสามารถกำหนดค่า Jackson ทั่วโลกได้ดังนี้:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonObjectMapperConfiguration implements Jackson2ObjectMapperBuilderCustomizer {

    @Override
    public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY);
    }

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.