Использование аннотации ResponseBody в Spring для возврата Json не работает

Я работаю над веб-приложением spring mvc, в котором я использую API визуализации Google для создания некоторых диаграмм. У меня есть класс модели, который содержит 2 массива, которые представляют данные, которые я отправляю в функцию, рисующую диаграмму (это то, что я хочу преобразовать в JSON).

Класс модели:

@Component
public class JsonResponse {

private List<Integer> percentages = new ArrayList<Integer>();
private List<String> topics = new ArrayList<String>();

public JsonResponse(){
}

public List<Integer> getPercentages() {
    return percentages;
}

public void setPercentages(List<Integer> percentages) {
    this.percentages = percentages;
}

public List<String> getTopics() {
    return topics;
}

public void setTopics(List<String> topics) {
    this.topics = topics;
}
}

Затем аннотированный класс Ive got a@Component`, который содержит метод, возвращающий объект модели (класса, который я написал выше), с заполненными атрибутами 2 arraylists.

@Component
public class ChartUtils {
    @Autowired
    public JsonResponse response;

    public JsonResponse listPieChartData( ModelAndView model ,int waveId ){

    //arraylists for chart generation
List<Integer> percentages = new ArrayList<Integer>();
List<String> topics = new ArrayList<String>();

    {... code for accessing the DB and processing some data and then populating the 2                  
     arraylists ... }

response.setTopics(topics);
response.setPercentages(percentages);

return response;}
}

Итак, класс контроллера, который имеет сопоставление для действия, которое я вызываю для сбора данных для создания диаграммы, и в котором я вызываю метод listPieChartData, из класса выше, и в котором я также использую аннотацию @ResponseBody это:

@Controller
public class ChartController {

@Autowired
public ChartUtils utils;

@Autowired
public JsonResponse response;

@RequestMapping(value = "/drawPieChart", method = RequestMethod.GET )
@ResponseBody
public JsonResponse drawPieChart( ModelAndView model,
        @RequestParam(value = "id", defaultValue = "-1") int waveId ) {

    return utils.listPieChartData(model,waveId ); }

Функция JavaScript, рисующая диаграмму:

function drawColumnChart(percentages, topics , div,width,height) {
    var data = new google.visualization.DataTable();

data.addColumn('string', 'Wave');
for (var i=0; i < topics.length; i++){
    data.addColumn( 'number', topics[i] ); 
}

    data.addRow( percentages );

    var wave=percentages[0];
    var options = {
        'title':'Generated Chart For '+wave,
        'backgroundColor': { fill: "none" },
        'is3D': true,
        'width':width,
        'height':height,
    };

var chart = new google.visualization.ColumnChart(document.getElementById(div));
chart.draw(data, options);

}

И вызов AJAX сопоставленного метода контроллера (для сбора данных), который, наконец, вызывает вышеуказанную функцию JS для получения диаграммы (я также отправляю параметр запроса int id для метода контроллера, я этого не писал)

$("#button").live("click", function(){

var arrayP, arrayT;
$.ajax({
    url: "drawPieChart",      
contentType: "application/json",
data: params,
success: function(data) {
    $.each(data, function(messageIndex, message) {
    if (messageIndex === 0) {
            arrayP = message;
    } else {
    arrayT = message;
    }
        });
    drawPieChart(arrayP, arrayT,'chart_div',600,400);
    }
    });  
});

Я знаю, что это много кода :) но это довольно простой код, чтобы лучше понять поток, вот как это работает:

Из кнопки ввода, которую я вызываю, с помощью AJAX сопоставленный метод с действием drawPieChart (которое находится в классе ChartController), эти методы отправляют ответ, вызывая метод listPieChart (из класса ChartUtils), который возвращает объект JsonResponse , (который содержит 2 массива). Это JsonResponse должно быть преобразовано в JSON, потому что в запросе AJAX я говорю, что запросу требуется ввод JSON (через contentType: "application/json"), и он должен получить его, потому что я использую @ResponseBody в методе контроллера. сопоставляется для этого запроса.

Я получаю этот ответ:

Ресурс, идентифицированный этим запросом, способен генерировать ответы только с характеристиками, недопустимыми в соответствии с заголовками «принять» запроса ().
(Статус HTTP 406)

Пожалуйста, поправьте меня, где я ошибаюсь, я просто не могу заставить это работать, и я не могу понять, почему...

И мой servlet-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc       
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans    
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context     
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

  <!-- DispatcherServlet Context: defines this servlet's request-processing      
infrastructure -->

  <!-- Enables the Spring MVC @Controller programming model -->
  <annotation-driven />

  <!-- Handles HTTP GET requests for /resources/** by efficiently serving up
      static resources in the ${webappRoot}/resources directory -->
  <resources mapping="/resources/**" location="/resources/" />

  <!-- Resolves views selected for rendering by @Controllers to .jsp resources
    in the /WEB-INF/views directory -->
  <beans:bean 
     class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/views/" />
    <beans:property name="suffix" value=".jsp" />
  </beans:bean>

  <context:component-scan base-package="com.bla.bla" />

  <beans:import resource="classpath:springJDBC.xml" />

</beans:beans>

person Adrian Bob    schedule 16.09.2012    source источник
comment
Можно ли добавить в справку @RequestMapping добавление products=application/json?   -  person arahant    schedule 16.09.2012
comment
Привет, я попробовал и получил тот же результат, я также использовал firebug для проверки запроса, а заголовок содержит приложение Content-Type/json, поэтому я действительно не знаю, в чем проблема...   -  person Adrian Bob    schedule 16.09.2012
comment
Дубликат stackoverflow. ком/вопросы/3340050/?   -  person Integrating Stuff    schedule 16.09.2012
comment
Посмотрев ответ на этот пост, я неt have any Jackson beans , or any json mapping in the negotiating resolver , so if that doesnне помогу, я неt think itс дублирующим сообщением   -  person Adrian Bob    schedule 16.09.2012
comment
Но у вас есть Джексон в пути к классам?   -  person Xaerxess    schedule 17.09.2012
comment
Нет, должен ли я добавить зависимость Джексона в свой pom.xml? Это все, что нужно?   -  person Adrian Bob    schedule 17.09.2012
comment
Добавил зависимость для Джексона и теперь все работает, спасибо Xaerxess.   -  person Adrian Bob    schedule 17.09.2012


Ответы (2)


Итак, проблема заключалась в том, что у меня не было всех зависимостей Джексона, объявленных в pom.xml. Это зависимости для вашего проекта maven на случай, если вы хотите, чтобы Spring 3 автоматически сериализовал объект для вас, используя аннотацию @ResponseBody, в качестве ответа от метода. Нубский материал, но я не видел упоминания об этом в найденных мною примерах.

  <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-jaxrs</artifactId>
        <version>1.6.1</version>
    </dependency>

        <dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.9</version>
</dependency>

<dependency>
       <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.9</version>
</dependency>

Кроме того, мне пришлось изменить некоторые вещи в вызове ajax для вызова метода, который возвращает объект json с данными для создания диаграммы:

$("#buttonPieGenerate").live("click", function(){

    $.ajax({
        url: "drawPieChart", //method from controller
        contentType: "application/json",
        data: params,
        success: function(data) {

        drawPieChart(data.percentages, data.topics,'chart_div',600,400);
        }
    });

});

Я получаю доступ к данным в объекте Json, который я получаю в ответ на вызов с помощью data.percentages , data.topics .

person Adrian Bob    schedule 20.09.2012

Небольшое обновление для мира 2015 года:

<dependency>
    <!-- Just placing this on the classpath will enable JSON for @ResponseBody -->
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.3</version>
</dependency>
person Michael Piefel    schedule 15.06.2015