2010-09-20 30 views
13

有谁知道是否有一个弹性MVC映射视图为Gson?我正在寻找类似org.springframework.web.servlet.view.json.MappingJacksonJsonView的东西。Google-GSON的Spring MVC映射视图?

理想的情况下,将采取我ModelMap并呈现为JSON,尊重我的renderedAttributes在ContentNegotiatingViewResolver声明

我们计划在应用程序中大量使用GSON,因为它似乎比杰克逊更安全,更好的设置。也就是说,为了实现本机JSON视图,我们需要拥有两个不同的JSON库。

在此先感谢!

[交叉张贴到Spring forums]

+2

小心详细说“看起来更安全,更好”?如何,更好地以什么方式? (或更安全,就此而言) – StaxMan 2011-03-18 05:07:54

+0

+1,正是我所寻找的。 – Jonik 2013-04-16 09:29:14

+0

对于任何人来到这里的春季引导5.0,请检查我的答案[强制春季使用GSON,而不是杰克逊](https://stackoverflow.com/a/48459787/6860188) – lordUhuru 2018-01-26 10:55:15

回答

5

我会建议延长AbstractView就像MappingJacksonJsonView一样。

就个人而言,对于JSON,我更喜欢使用@Responsebody,而只是返回对象而不是模型和视图,这使得它更容易测试。如果你想用GSON为此,只需创建一个自定义HttpMessageConverter这样的:

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 
import com.google.gson.JsonParseException; 
import com.google.gson.reflect.TypeToken; 
import com.vitalimages.string.StringUtils; 
import org.springframework.http.HttpInputMessage; 
import org.springframework.http.HttpOutputMessage; 
import org.springframework.http.MediaType; 
import org.springframework.http.converter.AbstractHttpMessageConverter; 
import org.springframework.http.converter.HttpMessageNotReadableException; 
import org.springframework.http.converter.HttpMessageNotWritableException; 
import org.springframework.stereotype.Component; 

import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.OutputStreamWriter; 
import java.lang.reflect.Type; 
import java.nio.charset.Charset; 
import java.sql.Timestamp; 

@Component 
public class GSONHttpMessageConverter extends AbstractHttpMessageConverter<Object> { 

    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 

    private GsonBuilder gsonBuilder = new GsonBuilder() 
      .excludeFieldsWithoutExposeAnnotation() 
      .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") 
      .registerTypeAdapter(Timestamp.class, new GSONTimestampConverter()); 

    public GSONHttpMessageConverter() { 
     super(new MediaType("application", "json", DEFAULT_CHARSET)); 
    } 

    @Override 
    protected boolean supports(Class<?> clazz) { 
     // should not be called, since we override canRead/Write instead 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public boolean canRead(Class<?> clazz, MediaType mediaType) { 
     return MediaType.APPLICATION_JSON.isCompatibleWith(mediaType); 
    } 

    public boolean canWrite(Class<?> clazz, MediaType mediaType) { 
     return MediaType.APPLICATION_JSON.isCompatibleWith(mediaType); 
    } 

    public void registerTypeAdapter(Type type, Object serializer) { 
     gsonBuilder.registerTypeAdapter(type, serializer); 
    } 

    @Override 
    protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { 
     try { 
      Gson gson = gsonBuilder.create(); 
      return gson.fromJson(StringUtils.convertStreamToString(inputMessage.getBody()), clazz); 
     } catch (JsonParseException e) { 
      throw new HttpMessageNotReadableException("Could not read JSON: " + e.getMessage(), e); 
     } 
    } 

    @Override 
    protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { 
     Type genericType = TypeToken.get(o.getClass()).getType(); 

     BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputMessage.getBody(), DEFAULT_CHARSET)); 
     try { 
      // See http://code.google.com/p/google-gson/issues/detail?id=199 for details on SQLTimestamp conversion 
      Gson gson = gsonBuilder.create(); 
      writer.append(gson.toJson(o, genericType)); 
     } finally { 
      writer.flush(); 
      writer.close(); 
     } 
    } 
} 

然后它在你的处理器适配器像这样添加到您的转换器列表:

@Bean 
public HandlerAdapter handlerAdapter() { 
    final AnnotationMethodHandlerAdapter handlerAdapter = new AnnotationMethodHandlerAdapter(); 
    handlerAdapter.setAlwaysUseFullPath(true); 
    List<HttpMessageConverter<?>> converterList = new ArrayList<HttpMessageConverter<?>>(); 
    converterList.addAll(Arrays.asList(handlerAdapter.getMessageConverters())); 
    converterList.add(jibxHttpMessageConverter); 
    converterList.add(gsonHttpMessageConverter); 
    handlerAdapter.setMessageConverters(converterList.toArray(new HttpMessageConverter<?>[converterList.size()])); 
    return handlerAdapter; 
} 
+0

你可以做同样的事情bean,但在'applicationContext.xml'中? – 4gus71n 2013-10-05 23:40:31

11

aweigold拉去大多数情况下,只是为了具体描述Spring 3.1基于Java的配置的解决方案,这就是我所做的。

spring-android-rest-template项目抓取GsonHttpMessageConverter.java

在您的MVC配置中注册您的GsonHttpMessageConverter消息转换器。

@EnableWebMvc 
public class WebConfig extends WebMvcConfigurerAdapter { 
    @Override 
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
    converters.add(new GsonHttpMessageConverter()); 
    } 
} 

春季文档概述了这个过程,但不是很清楚。为了使这个工作正常,我不得不延长WebMvcConfigurerAdapter,然后覆盖configureMesageConverters。做完这些之后,您应该可以在您的控制器方法中执行以下操作:

@Controller 
public class AppController { 
    @RequestMapping(value = "messages", produces = MediaType.APPLICATION_JSON_VALUE) 
    public List<Message> getMessages() { 
    // .. Get list of messages 
    return messages; 
    } 
} 

瞧! JSON输出。

+0

谢谢,这真的帮助了我!有了Spring 3.2.2和jackson,我无法摆脱它说的问题:406不合适。我这样做,它的工作,但我也不得不添加到服务xml文件。 – user1051218 2013-05-30 06:38:00