Spring MVC mapping view for Google-GSON?

后端 未结 2 1978
孤城傲影
孤城傲影 2021-01-31 21:46

Does anyone know if there is a Spring MVC mapping view for Gson? I\'m looking for something similar to org.springframework.web.servlet.view.json.MappingJacksonJsonView.

相关标签:
2条回答
  • 2021-01-31 21:54

    aweigold got me most of the way there, but to concretely outline a solution for Spring 3.1 Java based configuration, here's what I did.

    Grab GsonHttpMessageConverter.java from the spring-android-rest-template project.

    Register your GsonHttpMessageConverter with the message converters in your MVC config.

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

    The Spring docs outline this process, but aren't crystal clear. In order to get this to work properly, I had to extend WebMvcConfigurerAdapter, and then override configureMesageConverters. After doing this, you should be able to do the following in your controller method:

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

    And voila! JSON output.

    0 讨论(0)
  • 2021-01-31 22:12

    I would recommend to extend AbstractView just like the MappingJacksonJsonView does.

    Personally, for JSON, I prefer to use @Responsebody, and just return the object rather than a model and view, this makes it easier to test. If you would like to use GSON for that, just create a custom HttpMessageConverter like this:

    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();
            }
        }
    }
    

    And then add it to your converter list in your handler adapter like this:

    @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 讨论(0)
提交回复
热议问题