POST JSON ล้มเหลวด้วย 415 ประเภทสื่อที่ไม่รองรับ, Spring 3 mvc


171

ฉันพยายามส่งคำขอ POST ไปยัง servlet ส่งคำขอผ่าน jQuery ด้วยวิธีนี้:

var productCategory = new Object();
productCategory.idProductCategory = 1;
productCategory.description = "Descrizione2";
newCategory(productCategory);

โดยที่ newCategory คือ

function newCategory(productCategory)
{
  $.postJSON("ajax/newproductcategory", productCategory, function(
      idProductCategory)
  {
    console.debug("Inserted: " + idProductCategory);
  });
}

และ postJSON คือ

$.postJSON = function(url, data, callback) {
    return jQuery.ajax({
    'type': 'POST',
    'url': url,
    'contentType': 'application/json',
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
    });
};

ด้วย firebug ฉันเห็นว่า JSON ส่งอย่างถูกต้อง:

{"idProductCategory":1,"description":"Descrizione2"}

แต่ฉันได้รับ 415 ประเภทสื่อที่ไม่รองรับ Spring mvc controller มีลายเซ็นต์

    @RequestMapping(value = "/ajax/newproductcategory", method = RequestMethod.POST)
public @ResponseBody
Integer newProductCategory(HttpServletRequest request,
        @RequestBody ProductCategory productCategory)

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


คุณเปลี่ยนอะไรมาหลายวันแล้ว? นอกจากนี้จะไม่var productCategory = { idProductCategory: 1, description: "Descrizione2" };กระชับและอ่านง่ายกว่าใช่ไหม คุณต้องบอกให้สปริงยอมรับเป็นapplication/jsonพิเศษหรือไม่? พูดอีกอย่างคือมันคาดหวังว่าข้อมูลจะมาในรูปแบบหรือไม่?
เดฟนิวตัน

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

ไม่คุณไม่ใช่คุณได้รับมาจากโพสต์ JSON Ajax ซึ่งไม่เหมือนกับข้อมูลที่เข้ารหัสในแบบฟอร์ม
เดฟนิวตัน

1
คุณแน่ใจหรือไม่ว่าแจ็กสันยังคงมีอยู่ใน CLASSPATH ของคุณ
Tomasz Nurkiewicz

1
ถ้า u ส่งข้อความ / JSON แทน application / JSON U ได้รับข้อผิดพลาดเดียวกัน
Blacksonic

คำตอบ:


249

ฉันเคยทำสิ่งนี้มาก่อนด้วย Spring @ResponseBody และเป็นเพราะไม่มีส่วนหัวที่ยอมรับได้ส่งมาพร้อมกับคำขอ ยอมรับส่วนหัวอาจเป็นความเจ็บปวดในการตั้งค่าด้วย jQuery แต่สิ่งนี้ใช้ได้สำหรับฉันที่มา

$.postJSON = function(url, data, callback) {
    return jQuery.ajax({
    headers: { 
        'Accept': 'application/json',
        'Content-Type': 'application/json' 
    },
    'type': 'POST',
    'url': url,
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
    });
};

ส่วนหัวของ Content-Type ถูกใช้โดย @RequestBody เพื่อกำหนดรูปแบบของข้อมูลที่ถูกส่งจากไคลเอนต์ในคำขอ @ResponseBody ส่วนหัว accept ใช้เพื่อกำหนดรูปแบบที่จะส่งข้อมูลกลับไปยังลูกค้าในการตอบ นั่นเป็นเหตุผลที่คุณต้องมีทั้งสองส่วน


1
ส่วนหัว: {... } และ JSON.stringify (... ) เดินทางมาด้วยเสมอ
Tim Perry

1
ไม่ทราบว่าทำไมจึงไม่มีการบันทึกข้อมูลเพิ่มเติม ปัญหานี้ทำให้ฉันเสียเวลามาก ขอบคุณมาก!
Hugo Nava Kopp

ฉันคาดว่าสปริงจะสนับสนุนข้อมูลฟอร์มโดยค่าเริ่มต้น แต่ไม่รองรับ ดังนั้นขอบคุณสำหรับการแก้ปัญหา (ตอนนี้ค่อนข้างเก่า)
RiZKiT

ฉันใช้บุรุษไปรษณีย์เพื่อส่งคำขอเพิ่มเนื้อหาประเภท: '' application / json "ขอบคุณ
Janatbek Sharsheyev

21

การเพิ่มประเภทเนื้อหาลงในคำขอเมื่อapplication/jsonแก้ไขปัญหาแล้ว


18

ฉันมีปัญหาที่คล้ายกัน แต่พบว่าปัญหาคือฉันไม่ได้ระบุผู้สร้างเริ่มต้นสำหรับ DTO ที่มีคำอธิบายประกอบด้วย @RequestBody


สิ่งเดียวกันเกิดขึ้นกับฉัน ฉันมี 2 วิธีด้วยชื่อเดียวกันและได้รับ 415 ขอบคุณ!
Daniel Vilas-Boas

12

ฉันเชื่อว่าฉันวิ่งเข้าไปในปัญหาเดียวกัน หลังจากการต่อสู้กับ JSON นับไม่ถ้วนชั่วโมง JavaScript และเซิร์ฟเวอร์ฉันพบผู้ร้าย: ในกรณีของฉันฉันมีวัตถุวันที่ใน DTO วัตถุวันนี้ถูกแปลงเป็นสตริงเพื่อให้เราสามารถแสดงในมุมมองที่มี รูปแบบ: HH: มม.

เมื่อข้อมูล JSON ถูกส่งกลับวัตถุสตริงวันที่นี้จะต้องถูกแปลงกลับเป็นวัตถุวันที่เต็มรูปแบบดังนั้นเราจึงจำเป็นต้องมีวิธีการตั้งค่าใน DTO BUT ขนาดใหญ่คือคุณไม่สามารถมี 2 วิธีที่มีชื่อเดียวกัน (Overload) ใน DTO แม้ว่าพวกเขาจะมีพารามิเตอร์ประเภทต่าง ๆ (String vs Date) เพราะสิ่งนี้จะทำให้คุณมีข้อผิดพลาดประเภทสื่อที่ไม่สนับสนุน 415

นี่คือวิธีการควบคุมของฉัน

  @RequestMapping(value = "/alarmdownload/update", produces = "application/json", method = RequestMethod.POST)
  public @ResponseBody
  StatusResponse update(@RequestBody AlarmDownloadDTO[] rowList) {
    System.out.println("hola");
    return new StatusResponse();
  }

นี่คือตัวอย่าง DTO ของฉัน (id get / set และ preAlarm get methods ไม่รวมอยู่ในการย่อรหัส):

@JsonIgnoreProperties(ignoreUnknown = true)
public class AlarmDownloadDTO implements Serializable {

  private static final SimpleDateFormat formatHHmm = new SimpleDateFormat("HH:mm");

  private String id;
  private Date preAlarm;

  public void setPreAlarm(Date date) { 
    this.preAlarm == date;
  }
  public void setPreAlarm(String date) {    
    try {
      this.preAlarm = formatHHmm.parse(date);
    } catch (ParseException e) {
      this.preAlarm = null;
    } catch (NullPointerException e){
      this.preAlarm = null;
    }
  }
}

ในการทำให้ทุกอย่างทำงานคุณต้องลบเมธอดด้วยพารามิเตอร์ Date type ข้อผิดพลาดนี้น่าผิดหวังมาก หวังว่านี่จะช่วยประหยัดเวลาในการดีบักได้หลายชั่วโมง


ขอบคุณ - หรือคุณสามารถเปลี่ยนชื่อหนึ่งใน setters ได้ ฉันมีทั้งpublic void setParameters(List<Parameter> parameters)& public void setParameters(Parameter... parameters)วิธีในถั่วเปลี่ยนหลังเพื่อaddParametersแก้ไขปัญหาสำหรับฉัน
Conor Svensson

นี่ไม่ใช่ปัญหาที่ร่างกายคือ this.preAlarm == date มากกว่า this.preAlarm = date ใช่ไหม
Michael เรียกคืนโมนิก้า Cellio

12

ฉันพบปัญหาที่คล้ายกันและนี่คือวิธีที่ฉันจะแก้ไข

ปัญหาเกิดจากกระบวนการแปลงจาก JSON เป็น Java หนึ่งต้องมีไลบรารี jackson เวลาทำงานที่ถูกต้องเพื่อให้การแปลงเกิดขึ้นอย่างถูกต้อง

เพิ่มไหต่อไปนี้ (ผ่านการพึ่งพาหรือโดยการดาวน์โหลดและเพิ่มใน classpath

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>

สิ่งนี้ควรแก้ไขปัญหา

รหัสเสร็จสมบูรณ์:

function() {
  $.ajax({
    type: "POST",
    url: "saveUserDetails.do",
    data: JSON.stringify({
      name: "Gerry",
      ity: "Sydney"
    }),
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    success: function(data) {
      if (data.status == 'OK')
        alert('Person has been added');
      else
        alert('Failed adding person: ' + data.status + ', ' + data.errorMessage);
}

และลายเซ็นควบคุมมีลักษณะดังนี้:

@RequestMapping(value = "/saveUserDetails.do", method = RequestMethod.POST)
public @ResponseBody Person addPerson( @RequestBody final  Person person) {

หวังว่านี่จะช่วยได้


เพียง แต่jackson-databindเป็นสิ่งจำเป็น
Alex78191

8

ฉันประสบปัญหานี้เมื่อฉันรวมบูทสปริงกับสปริง mvc ฉันแก้ไขได้โดยเพียงแค่เพิ่มการพึ่งพาเหล่านี้

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>

5

บันทึกย่อขนาดเล็ก - สะดุดเมื่อเกิดข้อผิดพลาดเดียวกันนี้ในขณะที่การพัฒนาโปรแกรมประยุกต์บนเว็บ ความผิดพลาดที่เราพบโดยการเล่นกับบริการที่มีโปสเตอร์ Firefox คือทั้งฟิลด์และค่าใน Json ควรถูกล้อมรอบด้วยเครื่องหมายคำพูดคู่ เช่น ..

[ {"idProductCategory" : "1" , "description":"Descrizione1"}, 
  {"idProductCategory" : "2" , "description":"Descrizione2"} ]

ในกรณีของเราเราเติม json ผ่าน javascript ซึ่งอาจสร้างความสับสนเล็กน้อยเมื่อมันมาพร้อมกับการจัดการกับคำพูดเดี่ยว / คู่จากสิ่งที่ฉันเคยได้ยิน

มีการกล่าวถึงอะไรก่อนหน้านี้ในการโพสต์นี้และโพสต์อื่น ๆ เช่นรวมถึงส่วนหัว 'ยอมรับ' และ 'ประเภทเนื้อหา' เช่นกัน

หวังว่าจะช่วย


3

ฉันจัดการวิธีทำให้มันใช้งานได้ บอกฉันในกรณีที่ฉันผิด ฉันใช้วิธีเดียวเท่านั้นในการทำให้เป็นอนุกรม / deserialize: ฉันลบคำอธิบายประกอบทั้งหมดที่เกี่ยวข้องกับ ( @JSONSerializeและ@JSONDeserialize) นี้และ Serializers และ Deserializers ที่ลงทะเบียนในCustomObjectMapperชั้นเรียน ฉันไม่พบบทความอธิบายพฤติกรรมนี้ แต่ฉันแก้ไขด้วยวิธีนี้ หวังว่ามันจะมีประโยชน์


เกิดขึ้นกับฉันเหมือนกัน! คำอธิบายใด ๆ ว่าทำไมมันเกิดขึ้น?
กระทืบ

คุณช่วยอธิบายรายละเอียดวิธีการของคุณได้ไหม?
Dipanshu Verma

1

ผมมีปัญหาเหมือนกัน. ฉันต้องทำตามขั้นตอนเหล่านี้เพื่อแก้ไขปัญหา:

1. ตรวจสอบให้แน่ใจว่าคุณมีการอ้างอิงต่อไปนี้:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>${jackson-version}</version> // 2.4.3
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson-version}</version> // 2.4.3
    </dependency>

2. สร้างตัวกรองต่อไปนี้:

    public class CORSFilter extends OncePerRequestFilter {

        @Override
        protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {

            String origin = request.getHeader("origin");
            origin = (origin == null || origin.equals("")) ? "null" : origin;
            response.addHeader("Access-Control-Allow-Origin", origin);
            response.addHeader("Access-Control-Allow-Methods", "POST, GET, PUT, UPDATE, DELETE, OPTIONS");
            response.addHeader("Access-Control-Allow-Credentials", "true");
            response.addHeader("Access-Control-Allow-Headers",
                    "Authorization, origin, content-type, accept, x-requested-with");

            filterChain.doFilter(request, response);
        }
    }

3. ใช้ตัวกรองด้านบนสำหรับคำขอใน web.xml

    <filter>
        <filter-name>corsFilter</filter-name>
        <filter-class>com.your.package.CORSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>corsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

ฉันหวังว่านี่จะเป็นประโยชน์กับใครบางคน


jackson-coreเป็นพึ่งพาของjackson-databindจึงไม่จำเป็นที่จะเพิ่มได้โดยตรง
Alex78191

1
ทำไมจึงจำเป็นต้องเพิ่มตัวกรอง CORS
Alex78191

1

Spring boot + spring mvn

กับปัญหา

@PostMapping("/addDonation")
public String addDonation(@RequestBody DonatorDTO donatorDTO) {

ด้วยวิธีการแก้ปัญหา

@RequestMapping(value = "/addDonation", method = RequestMethod.POST)
@ResponseBody
public GenericResponse addDonation(final DonatorDTO donatorDTO, final HttpServletRequest request){

0

ฉันแก้ไขปัญหานี้ด้วยการเพิ่มการเชื่อมโยงข้อมูล jackson-json เข้ากับ pom ของฉัน

<dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.6.3</version>
</dependency>

0

ใน Model Class ของคุณเพิ่มบันทึกย่อคุณสมบัติ json ยังมีตัวสร้างเริ่มต้น

@JsonProperty("user_name")
private String userName;

@JsonProperty("first_name")
private String firstName;

@JsonProperty("last_name")
private String lastName;

0

ฉันมีปัญหาเดียวกัน เพิ่ม

<mvc:annotation-driven />
<mvc:default-servlet-handler />

เพื่อสปริง xml แก้ไขมัน


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