ทำให้เป็นอันดับกับ Jackson (JSON) - รับ“ ไม่พบ serializer”?


262

ฉันได้รับการยกเว้นเมื่อพยายามทำให้เป็นวัตถุที่ง่ายมากโดยใช้แจ็คสัน ข้อผิดพลาด:

org.codehaus.jackson.map.JsonMappingException: ไม่พบ serializer สำหรับคลาส MyPackage.TestA และไม่พบคุณสมบัติในการสร้าง BeanSerializer (เพื่อหลีกเลี่ยงข้อยกเว้นให้ปิดการใช้งาน SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS)

ด้านล่างเป็นคลาสและรหัสอย่างง่ายในการทำให้เป็นอนุกรม

ใครสามารถบอกฉันได้ว่าทำไมฉันถึงได้รับข้อผิดพลาดนี้?

public class TestA {
    String SomeString = "asd";
}

TestA testA = new TestA();
ObjectMapper om = new ObjectMapper();
try {
    String testAString = om.writeValueAsString(testA); // error here!

    TestA newTestA = om.readValue(testAString, TestA.class);
} catch (JsonGenerationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (JsonMappingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

ฉันเขียนโพสต์เกี่ยวกับวิธีเขียน Serializer แบบกำหนดเองกับ Jacksonที่อาจเป็นประโยชน์กับบางคน
Sam Berry

คำตอบ:


329

ตามที่อธิบายไว้แล้วการกำหนดค่าเริ่มต้นของObjectMapperอินสแตนซ์คือการเข้าถึงคุณสมบัติที่เป็นเขตข้อมูลสาธารณะเท่านั้นหรือมีตัวรับสัญญาณสาธารณะ / ตัวตั้งค่า ทางเลือกอื่นในการเปลี่ยนคำจำกัดความของคลาสเพื่อทำให้ฟิลด์เป็นสาธารณะหรือเพื่อให้เป็นผู้ได้รับ / setter สาธารณะคือการระบุVisibilityCheckerกฎการมองเห็นของคุณสมบัติที่แตกต่างกัน Jackson 1.9 ให้ObjectMapper.setVisibility()วิธีการที่สะดวกในการทำเช่นนั้น สำหรับตัวอย่างในคำถามเดิมฉันมีแนวโน้มที่จะกำหนดค่านี้เป็น

myObjectMapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);

สำหรับแจ็คสัน> 2.0:

myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

สำหรับข้อมูลเพิ่มเติมและรายละเอียดเกี่ยวกับตัวเลือกการกำหนดค่าที่เกี่ยวข้องผมขอแนะนำให้อ่านJavaDocs ObjectMapper.setVisibility()บน


59
สิ่งนี้ใช้ได้สำหรับฉัน ในฐานะของ Jackson 2.0 ObjectMapper # setVisibility ใช้ PropertyAccessor เป็นอาร์กิวเมนต์แรก ผู้ออกตั๋วที่เทียบเท่าคือ myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
Dan Robinson

@DanRobinson ฉันใช้เหมือนกัน แต่จริงๆแล้วฉันกำลังสร้างไฟล์ yaml ดังนั้นสำหรับ JSONString เป็น: {"term":{"call_failed":"true"}}มันกำลังสร้างโครงสร้าง yaml เป็น: filter: map: term: map: call_failed: "true"ทำไมมันสร้างmapคำหลัก? ฉันจะลบออกได้อย่างไร
Manish Kumar

7
ฉันอาจใช้เวลา 8 ชั่วโมงกับข้อผิดพลาดนี้โดยไม่ทราบว่าวิธีการทะเยอทะยานของฉันไม่มี "สาธารณะ" เลย .. ดังนั้นโง่
Mike Kellogg

1
ฉันได้รับข้อผิดพลาดนี้ในขณะที่แปลง ClientResponse เป็น string โดยใช้ object mapper
VdeX

1
นอกจากนี้คุณยังสามารถเพิ่มคำอธิบายประกอบที่@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)อยู่เหนือชั้นเรียนของคุณ
veben

74

สำหรับแจ็คสันที่จะทำให้เป็นอนุกรมคลาสนั้นSomeStringฟิลด์จำเป็นต้องเป็นpublic(ตอนนี้เป็นการแยกระดับแพ็กเกจ) หรือคุณต้องกำหนดเมธอด getter และ setter สำหรับมัน


5
โปรดทราบว่าคำตอบนี้ไม่ถูกต้อง - ฟิลด์ไม่จำเป็นต้องเป็นแบบสาธารณะหรือมีผู้ทะเยอทะยานและผู้ตั้งค่า ในอีกคำตอบสำหรับคำถามนี้ฉันได้จัดเตรียมการกำหนดค่าทางเลือกที่ไม่ต้องการการเปลี่ยนแปลงโครงสร้างข้อมูลดั้งเดิมที่จะถูกทำให้เป็นอนุกรม (de)
โปรแกรมเมอร์ Bruce

9
คำตอบมีประโยชน์แม้ว่าจะไม่ถูกต้อง 100% ฉันลืมที่จะใส่ 'สาธารณะ' ลงใน vars ของฉันและสิ่งนี้ชี้ให้เห็นว่า ขอบคุณ!
ChrisPhoenix

53

ฉันมีปัญหาเดียวกันในซอร์สโค้ดของฉัน ฉันเพิ่งเพิ่ม

ทะเยอทะยาน

และ

หมา

ปัญหาได้รับการแก้ไข


1
พยายามหลายสิ่งหลายอย่างและวิธีแก้ปัญหาก็ง่ายเหมือนนี้ .... และมันบอกว่ามันค่อนข้างชัดเจน: "ไม่มีคุณสมบัติที่ค้นพบที่จะสร้าง"
aks

2
@PhilipRego เขาหมายถึงเขาเพิ่มทะเยอทะยานและผู้ตั้งค่าสำหรับฟิลด์
Paul

ฉันใช้ห้องสมุด lombok ดังนั้นฉันแค่เพิ่ม Anteration Getter และ Setter และทุกอย่างก็โอเค ขอบคุณ
Rahmat Hidayat

ใช่ getters และ setters จะใช้สำหรับแจ็คสัน serialization./deserialization
Ikhiloya Imokhai

25

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

ตามที่แนะนำในข้อยกเว้นฉันเพิ่มบรรทัดต่อไปนี้เพื่อหลีกเลี่ยงความล้มเหลวในถั่วที่ว่างเปล่า:

สำหรับแจ็คสัน 1.9

myObjectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);

สำหรับ Jackson 2.X

myObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

คุณสามารถหาตัวอย่างง่ายๆในแจ็คสันปิดการใช้งาน fail_on_empty_beans


9

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

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)

7

หากคุณสามารถแก้ไขคลาสที่มีวัตถุนั้นฉันมักจะเพิ่มคำอธิบายประกอบ

import com.fasterxml.jackson.annotation.JsonIgnore;

@JsonIgnore 
NonSerializeableClass obj;

2
ข้อผิดพลาดนี้เกิดขึ้นเมื่อคลาสของคุณมีเมธอดที่ชื่อขึ้นต้นด้วย get ... ตัวอย่างเช่น NonSerializableClass getMyNonSerializableObject () แจ็คสันพยายามที่จะทำให้เป็นอันดับและล้มเหลว หากต้องการแก้ไขปัญหานี้ให้เพิ่ม @JsonIgnore หรือเปลี่ยนชื่อวิธี
Alexey Podlasov

1
ใช้รุ่นที่เก่ากว่า:org.codehaus.jackson.annotate.JsonIgnore
AlikElzin-kilaka

6

ข้อผิดพลาดนี้จะเกิดขึ้นถ้าคุณลืมที่จะเพิ่มเมธอด. build () ลงในสถานะส่งคืนของคุณ

return Response.status(Status.OK);         // fails
return Response.status(Status.OK).build(); // works

ฉันได้รับข้อผิดพลาดต่อไปนี้โดยไม่มีการสร้างวิธี ():

org.codehaus.jackson.map.JsonMappingException: No serializer found for class com.sun.jersey.core.spi.factory.ResponseBuilderImpl

4

SpringBoot2.0, ฉันแก้ไขได้โดยทำตามรหัส:

@Bean public ObjectMapper objectMapper() {
 return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);}

1
คุณควรให้แบบจำลองของคุณมีวิธีทะเยอทะยานและตัวตั้ง
Janus

1
ยินดีต้อนรับสู่ SO! ขอบคุณสำหรับการมีส่วนร่วม โปรดเพิ่มคำอธิบายให้กับคำตอบของคุณดังนั้นจึงเป็นที่ชัดเจนว่ารหัสทำงานอะไรทำงานอย่างไรและตอบได้อย่างไร
Max Vollmer

สิ่งนี้ช่วยฉัน! แต่ในความคิดของฉันคุณควรแทรก ObjectMapper ของบริบทและกำหนดค่าในภายหลังแทนที่จะสร้างใหม่
RoBeaToZ

3

สำหรับแอ็พพลิเคชัน Oracle Java ให้เพิ่มสิ่งนี้หลังจากการObjectMapperสร้างอินสแตนซ์:

mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

2

ฉันมีปัญหาคล้ายกันกับการโหลดขี้เกียจผ่านวัตถุพร็อกซีจำศีล ได้รอบ ๆ มันโดยใส่คำอธิบายประกอบคลาสที่มีคุณสมบัติส่วนบุคคลที่ขี้เกียจโหลดด้วย:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

นี่เป็นการแก้ไขปัญหาของฉัน คุณบอกฉันได้มั้ย
Scarface

2

privateปัญหาที่เกิดขึ้นอาจเป็นเพราะคุณได้ประกาศตัวแปร หากคุณเปลี่ยนเป็นpublicใช้งานได้

ตัวเลือกที่ดีกว่าคือการใช้วิธี getter และ setter

นี่จะช่วยแก้ปัญหา!


2

ฉันพบอย่างน้อยสามวิธีในการทำเช่นนี้:

  1. เพิ่มpublic gettersในเอนทิตีของคุณที่คุณพยายามทำให้เป็นอันดับ;
  2. public gettersเพิ่มคำอธิบายประกอบที่ด้านบนของกิจการในกรณีที่คุณไม่ต้องการ นี้จะเปลี่ยนค่าเริ่มต้นสำหรับแจ็คสันจากVisbility=DEFAULTการ@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)ที่การปรับเปลี่ยนใด ๆ เข้าถึงได้รับการยอมรับ;
  3. คุณสามารถเปลี่ยนทั่วโลกโดยการตั้งค่าObjectMapper objectMapperInstance.setVisibility(JsonMethod.FIELD, Visibility.ANY);สิ่งนี้ควรหลีกเลี่ยงหากคุณไม่ต้องการฟังก์ชันนี้ทั่วโลก

เลือกตามความต้องการของคุณ


2

นี่คือสามตัวเลือก:

  1. ข้อมูล / คลาสที่เข้าถึงต้องมี public
  2. ถ้าไม่ใช่publicให้เพิ่มตัวตั้งและตัวตั้ง
  3. หรือเพิ่ม @JsonIgnore("context")

1

โปรดใช้สิ่งนี้ในระดับชั้นเรียนสำหรับ bean:

@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})

1

การเพิ่ม setter และ getter จะแก้ปัญหาตามที่ได้รับการแก้ไขสำหรับฉัน สำหรับอดีต:

public class TestA {
    String SomeString = "asd";

    public String getSomeString () {        return SomeString ;     }

    public void setSomeString (String SS ) {        SomeString = SS ;   } 
}


0

แม้ว่าฉันจะเพิ่ม getters และ setters แต่ฉันก็ได้รับข้อผิดพลาดเดียวกัน ต่อมาฉันก็พบข้อผิดพลาดนั่นคือโดยคำแนะนำของ Sonar ฉันได้ตรวจสอบตัวรับสัญญาณและตัวตั้งค่าตามที่ได้รับการป้องกันซึ่งทำให้เกิดปัญหา เมื่อฉันแก้ไขว่ามันทำงานเป็น exppected


0

ใน spring boot 2.2.5

หลังจากเพิ่ม getter และ setter

ฉันเพิ่ม @JsonIgnore ที่ด้านบนของฟิลด์

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