2014-02-05 2 views
23

У меня естьпараметр JSON в весеннем MVC контроллер

@RequestMapping(method = RequestMethod.GET) 
@ResponseBody 
SessionInfo register(UserProfile profileJson){ 
    ... 
} 

прохожу profileJson так:

http://server/url?profileJson={"email": "[email protected]"} 

, но мой объект profileJson имеет все нулевые поля. Что я должен сделать, чтобы весна разобрала моего json?

+0

Передача JSON в параметр запроса не имеет смысла. Вам нужно как минимум URL-кодировать его. – ashes999

+0

Я его urlencoding. –

+1

Вы передаете json в качестве параметра URL не как тело (которое является значением по умолчанию). Передача JSON в качестве параметра вообще не имеет смысла. Аннотируйте аргумент метода с помощью '@ RequestParam'. Однако, как уже упоминалось, вы должны передавать его как тело запроса и, возможно, также как POST вместо запроса GET. –

ответ

24

Это может быть сделано с помощью пользовательского редактора, который преобразует JSON в UserProfile объект:

public class UserProfileEditor extends PropertyEditorSupport { 

    @Override 
    public void setAsText(String text) throws IllegalArgumentException { 
     ObjectMapper mapper = new ObjectMapper(); 

     UserProfile value = null; 

     try { 
      value = new UserProfile(); 
      JsonNode root = mapper.readTree(text); 
      value.setEmail(root.path("email").asText()); 
     } catch (IOException e) { 
      // handle error 
     } 

     setValue(value); 
    } 
} 

Это для регистрации редактора в классе контроллера :

@InitBinder 
public void initBinder(WebDataBinder binder) { 
    binder.registerCustomEditor(UserProfile.class, new UserProfileEditor()); 
} 

И это, как использовать редактор, чтобы маршализацию параметр JSONP:

+0

. Это выглядит так универсально, мне интересно, действительно ли нужно писать и регистрировать собственный редактор для каждого класса, который я хочу проанализировать таким образом. –

+3

Добавление этого к диспетчерскому сервлета XML работало для меня \t \t \t \t <боб \t \t класс = "org.springframework.http.converter.json.MappingJackson2HttpMessageConverter "/> \t \t \t ' – Yahiya

+0

Это может быть еще проще с помощью' Конвертер'. См. Мой [ответ для примера] (https://stackoverflow.com/a/50350428/238134). – deamon

-5

Просто добавьте @RequestBody аннотацию перед этими парами

+0

Это не работает. Я получаю HTTP 415: сервер отказался от этого запроса, потому что объект запроса находится в формате, который не поддерживается запрошенным ресурсом для запрошенного метода. –

+2

'@ RequestBody' по умолчанию просматривает тело запроса. Содержимое OP - это параметр запроса, отправленный как часть строки запроса. –

+0

эта работа для меня. Я использую '@ RestController' – AhmadReza

30

Решение этой задачи настолько просто и просто, что вы будете смеяться, но прежде чем я доберусь до него, позвольте мне вначале подчеркнуть, что ни один уважающий себя Java-разработчик никогда не будет, и я имею в виду ВСЕГДА работать с JSON без использования высококачественной JSON-библиотеки Jackson.

Jackson является не только рабочей лошадкой и библиотекой JSON для разработчиков Java, но и предоставляет целый набор вызовов API, что делает интеграцию JSON с Java куском торта (вы можете скачать Джексон на http://jackson.codehaus.org/).

Теперь для ответа. Если предположить, что у вас есть UserProfile POJO, который выглядит примерно так:

public class UserProfile { 

private String email; 
// etc... 

public String getEmail() { 
    return email; 
} 

public void setEmail(String email) { 
    this.email = email; 
} 

// more getters and setters... 
} 

... то ваш метод Spring MVC, чтобы преобразовать имя параметра GET «profileJson» со значением JSON из { «электронной почты»: «mymail @ gmail.com .com "} будет выглядеть следующим образом в вашем контроллере:

import org.codehaus.jackson.JsonParseException; 
import org.codehaus.jackson.map.JsonMappingException; 
import org.codehaus.jackson.map.ObjectMapper; // this is your lifesaver right here 

//.. your controller class, blah blah blah 

@RequestMapping(value="/register", method = RequestMethod.GET) 
public SessionInfo register(@RequestParam("profileJson") String profileJson) 
throws JsonMappingException, JsonParseException, IOException { 

    // now simply convert your JSON string into your UserProfile POJO 
    // using Jackson's ObjectMapper.readValue() method, whose first 
    // parameter your JSON parameter as String, and the second 
    // parameter is the POJO class. 

    UserProfile profile = 
      new ObjectMapper().readValue(profileJson, UserProfile.class); 

     System.out.println(profile.getEmail()); 

     // rest of your code goes here. 
} 

Bam! Все готово. Я бы посоветовал вам изучить основную часть Jackson API, потому что, как я уже сказал, это спасатель. Например, вы вообще возвращаете JSON из своего контроллера? Если это так, все, что вам нужно сделать, это включить JSON в вашу библиотеку и вернуть POJO, и Джексон автоматически преобразует ее в JSON. Вы не можете стать намного легче, чем это. Ура! :-)

+1

Мне хотелось бы указать некоторый параметр для аннотации @RequestParameter для этого. –

+2

Не рекомендуется создавать для каждого запроса ObjectMapper. Контроллер должен иметь поле ObjectMapper. –

+4

Собственно, это неправильно. Прежде всего, я предполагаю, что «поле» означает переменную экземпляра класса контроллера. Во-вторых, точкой моего примера было продемонстрировать использование ObjectMapper, а не давать лучшие практики и вникать в более мелкие детали архитектуры создания объекта. И в-третьих, и самое главное, наличие ObjectMapper в качестве переменной экземпляра контроллера - это просто плохая практика, потому что контроллеры Spring по умолчанию являются одиночными. Правильный подход будет соответствовать стандартным шаблонам MVC и Autowire - классу услуг, который содержит ObjectMapper. –

1

Это действительно решает мою непосредственную проблему, но мне все же интересно узнать, как вы можете передать несколько объектов JSON через вызов AJAX.

Лучший способ сделать это - иметь объект-обертку, содержащий два (или несколько) объектов, которые вы хотите передать. Затем построить свой объект JSON как массив из двух объектов, т.е.

[ 
    { 
    "name" : "object1", 
    "prop1" : "foo", 
    "prop2" : "bar" 
    }, 
    { 
    "name" : "object2", 
    "prop1" : "hello", 
    "prop2" : "world" 
    } 
] 

Затем в методе контроллера вы получаете тело запроса в виде одного объекта и извлечь два содержали объекты. i.e:

@RequestMapping(value="/handlePost", method = RequestMethod.POST, consumes = {  "application/json" }) 
public void doPost(@RequestBody WrapperObject wrapperObj) { 
    Object obj1 = wrapperObj.getObj1; 
    Object obj2 = wrapperObj.getObj2; 

    //Do what you want with the objects... 


} 

Объект обертки будет выглядеть примерно так ...

public class WrapperObject {  
private Object obj1; 
private Object obj2; 

public Object getObj1() { 
    return obj1; 
} 
public void setObj1(Object obj1) { 
    this.obj1 = obj1; 
} 
public Object getObj2() { 
    return obj2; 
} 
public void setObj2(Object obj2) { 
    this.obj2 = obj2; 
} 

} 
Смежные вопросы