2010-09-20 13 views
13

Czy ktoś wie, czy istnieje widok mapowania MVC Spring dla Gson? Szukam czegoś podobnego do org.springframework.web.servlet.view.json.MappingJacksonJsonView.Wiosenny widok mapowania MVC dla Google-GSON?

Idealnie byłoby zabrać ModelMap i uczynić go jako JSON, przestrzegając moich renderedAttributes określone w deklaracji ContentNegotiatingViewResolver

planujemy używać Gson obszernie we wniosku, jak wydaje się bezpieczniejsze i lepiej niż Jackson. To powiedziawszy, rozwiewa nas potrzeba posiadania dwóch różnych bibliotek JSON w celu tworzenia natywnych widoków JSON.

Z góry dziękuję!

[cross-wysłana do Spring forums]

+2

Dbać o opracowanie "wydaje się bezpieczniej i lepiej"? Jak w, lepiej w jaki sposób? (lub bezpieczniej, jeśli o to chodzi) – StaxMan

+0

+1, dokładnie to, czego szukałem. – Jonik

+0

Dla każdego, kto przyszedł tutaj od wiosny rozruch 5.0, sprawdź moją odpowiedź [wymuś sprężynę, aby użyć GSON, zamiast Jacksona] (https://stackoverflow.com/a/48459787/6860188) – lordUhuru

Odpowiedz

5

Polecam do przedłużenia AbstractView podobnie jak MappingJacksonJsonView robi.

Osobiście, dla JSON, wolę używać @Responsebody i po prostu zwracam obiekt, a nie model i widok, co ułatwia testowanie. Jeśli chcesz użyć GSON za to, po prostu utworzyć niestandardowy HttpMessageConverter tak:

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

a następnie dodać go do swojej listy kalkulator w karty handler jak ten:

@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

Czy możesz zrobić to samo z fasola, ale w 'applicationContext.xml'? – 4gus71n

11

aweigold Got Me w większości przypadków, ale aby konkretnie przedstawić rozwiązanie dla konfiguracji opartej na Java 3.1 Spring, oto co zrobiłem.

Uchwyć GsonHttpMessageConverter.java z projektu spring-android-rest-template.

Zarejestruj swój GsonHttpMessageConverter za pomocą konwerterów wiadomości w konfiguracji MVC.

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

Dokumenty źródłowe wiosenne opisują ten proces, ale nie są krystalicznie jasne. Aby to działało poprawnie, musiałem przedłużyć WebMvcConfigurerAdapter, a następnie zastąpić configureMesageConverters. Po wykonaniu tej czynności powinieneś wykonać następujące czynności w swojej metodzie sterowania:

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

I voila! Wyjście JSON.

+0

Dziękuję, to mi bardzo pomogło! Ze Spring 3.2.2 i Jacksona nie mogłem pozbyć się problemu, który brzmi: 406 nie jest dostępny. Zrobiłem to i zadziałało, ale musiałem również dodać do pliku xml usługi. – user1051218

Powiązane problemy