2016-03-18 11 views
4

Bir dinlenme api tüketen ve bir dinlenme api sunan bir SpringBoot uygulaması yazdım. Model pojo'mın camelCase adında özellikleri var. Uygulamanın tükettiği json, under_score özellik isimlerine sahip. Uygulamanın ürettiği json, under_score özellik isimlerine sahip. Marshalling/unmarshalling sırasında otomatik olarak Java ve json isimleri arasında dönüşüm yapacak bir PropertyNamingStrategy kullanmak istiyorum.SpringBoot'ta RestTemplate için PropertyNamingStrategy nasıl ayarlanır?

Bunu halledebilecek bir adlandırma stratejisi belirlemeye çalışan Java yapılandırmasına sahibim; Benim dinlenme hizmeti yanıtı için json Java POJOs dönüştürür zaman

/** 
* Configuration for Rest api. 
* <p> 
* Created by emurphy on 2/25/16. 
*/ 
@Configuration 
    public class RestConfig 
    { 
     /** 
     * Bean to make jackson automatically convert from 
     * camelCase (java) to under_scores (json) in property names 
     * 
     * @return ObjectMapper that maps from Java camelCase to json under_score names 
     */ 
     @Bean 
     public ObjectMapper jacksonObjectMapper() 
     { 
      return new ObjectMapper().setPropertyNamingStrategy(new UpperCaseUnderscoreStrategy()); 
     } 

     /** 
     * Property naming strategy that converts both ways between camelCase and under_score 
     * property names. 
     */ 
     public static class UpperCaseUnderscoreStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase 
     { 
      /** 
      * Converts camelCase to under_score and 
      * visa versa. The idea is that this 
      * name strategy can be used for both 
      * marshalling and unmarshaling. 
      * 
      * For example, "userName" would be converted to 
      * "user_name" and conversely "user_name" would 
      * be converted to "userName". 
      * 
      * @param input formatted as camelCase or under_score string 
      * @return input converted to opposite format 
      */ 
      @Override 
      public String translate(String input) 
      { 
       if (input == null || input.length() == 0) 
       { 
        return input; // garbage in, garbage out 
       } 

       // 
       // we always take the first character; 
       // this preserves initial underscore 
       // 
       StringBuilder sb = new StringBuilder(); 

       final int length = input.length(); 
       int i = 0; 

       // 
       // skip initial underscores 
       // 
       while ((i < length) && ('_' == input.charAt(i))) 
       { 
        sb.append(input.charAt(i)); 
        i += 1; 
       } 

       while (i < length) 
       { 
        // 
        // find underscores, remove and capitalize next letter 
        // 
        while ((i < length) && ('_' != input.charAt(i)) && !Character.isUpperCase(input.charAt(i))) 
        { 
         sb.append(input.charAt(i)); 
         i += 1; 
        } 

        if(i < length) 
        { 
         if('_' == input.charAt(i)) 
         { 
          // underscore to uppercase 

          // 
          // skip underscores 
          // 
          while ((i < length) && ('_' == input.charAt(i))) 
          { 
           // skip underscores 
           i += 1; 
          } 

          // 
          // capitalize 
          // 
          if (i < length) 
          { 
           sb.append(Character.toUpperCase(input.charAt(i))); 
           i += 1; 
          } 
         } 
         else // uppercase to unscore + lowercase 
         { 
          sb.append('_'); 
          sb.append(Character.toLowerCase(input.charAt(i))); 
          i += 1; 
         } 
        } 
       } 
       return sb.toString(); 
      } 
     } 

Ben adlandırma stratejisinin tercüme yöntemi denir görebiliyorsun. Bununla birlikte, RestTemplate aracılığıyla bir dinlenme api tüketirken, bunun arandığını görmüyorum ve sonuçta ortaya çıkan pojiler gelen jsondan doğru şekilde yönlendirilmiyor; Adının çevirisi gereken tüm mülkler boş. Bu, çoğu mülkte @JsonProperty kullanmam için beni zorladı. Çok fazla mülküm ve çok fazla pojetim var - bu, SpringBoot'un yardım etmesi gereken çok beceriksiz bir çözüm. RestTemplate'ın gelen json adlarını under_score'dan camelCase'e dönüştürmek için kullanacağı bir PropertyNamingStrategy ayarlamamın bir yolu var mı?

Yardımlarınız için teşekkürler.

+0

Yapılandırma sınıfınızın en üstündeki ek açıklamalar nelerdir? – pczeus

+0

Maalesef, sorudaki kodu güncelledim. Temelde Yapılandırmada. Ana yapılandırmam başka bir dosyada ve At SpringBootApplication ek açıklamasına sahip. – Ezward

cevap

4

RestTemplate oluştururken, objectMapper ürününü sizinki ayarlamanız gerekir. Ayrıca, özel ObjectMapper'ınızı bir @Bean olarak bildirmeniz gerekir, böylece Spring tarafından tek bir satır olarak oluşturulur ve sizin için yönetilir. PropertyNamingStrategy için bunu 'yeni' yerine 'sınıflandırma' yapmak ve sınıfı statik olarak ilan etmek için yapın.

public class RestConfig 
{ 
    /** 
    * Bean to make jackson automatically convert from 
    * camelCase (java) to under_scores (json) in property names 
    * 
    * @return ObjectMapper that maps from Java camelCase to json under_score names 
    */ 
    @Bean 
    public ObjectMapper jacksonObjectMapper() 
    { 
     return new ObjectMapper().setPropertyNamingStrategy(propertyNamingStrategy()); 
    } 

    @Bean 
    public PropertyNamingStrategy propertyNamingStrategy() 
    { 
     return new UpperCaseUnderscoreStrategy(); 
    } 

    @Bean 
    public RestTemplate restTemplate() { 
     RestTemplate restTemplate = new RestTemplate(); 
     List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(); 
     MappingJackson2HttpMessageConverter jsonMessageConverter = new MappingJackson2HttpMessageConverter(); 
     jsonMessageConverter.setObjectMapper(jacksonObjectMapper()); 
     messageConverters.add(jsonMessageConverter); 
     restTemplate.setMessageConverters(messageConverters); 

     return restTemplate; 
    } 
} 

Ve sınıfınız ayrı bir dosyada mı? Statik olması gerekmiyor.

/** 
    * Property naming strategy that converts both ways between camelCase and under_score 
    * property names. 
    */ 
    public static class UpperCaseUnderscoreStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase 
    { 
     /** 
     * Converts camelCase to under_score and 
     * visa versa. The idea is that this 
     * name strategy can be used for both 
     * marshalling and unmarshaling. 
     * 
     * For example, "userName" would be converted to 
     * "user_name" and conversely "user_name" would 
     * be converted to "userName". 
     * 
     * @param input formatted as camelCase or under_score string 
     * @return input converted to opposite format 
     */ 
     @Override 
     public String translate(String input) 
     { 
      if (input == null || input.length() == 0) 
      { 
       return input; // garbage in, garbage out 
      } 

      // 
      // we always take the first character; 
      // this preserves initial underscore 
      // 
      StringBuilder sb = new StringBuilder(); 

      final int length = input.length(); 
      int i = 0; 

      // 
      // skip initial underscores 
      // 
      while ((i < length) && ('_' == input.charAt(i))) 
      { 
       sb.append(input.charAt(i)); 
       i += 1; 
      } 

      while (i < length) 
      { 
       // 
       // find underscores, remove and capitalize next letter 
       // 
       while ((i < length) && ('_' != input.charAt(i)) && !Character.isUpperCase(input.charAt(i))) 
       { 
        sb.append(input.charAt(i)); 
        i += 1; 
       } 

       if(i < length) 
       { 
        if('_' == input.charAt(i)) 
        { 
         // underscore to uppercase 

         // 
         // skip underscores 
         // 
         while ((i < length) && ('_' == input.charAt(i))) 
         { 
          // skip underscores 
          i += 1; 
         } 

         // 
         // capitalize 
         // 
         if (i < length) 
         { 
          sb.append(Character.toUpperCase(input.charAt(i))); 
          i += 1; 
         } 
        } 
        else // uppercase to unscore + lowercase 
        { 
         sb.append('_'); 
         sb.append(Character.toLowerCase(input.charAt(i))); 
         i += 1; 
        } 
       } 
      } 
      return sb.toString(); 
     } 
    } 
+0

Cevabınız için teşekkür ederiz. Bunu hayata geçirdim ama hala çalışmıyor. Pojo'larımdaki @JsonProperty ek açıklamalarını kaldırdığımda, yalnızca 'açıklamalar' gibi basit adlara sahip mülklerin, aramayı yaptığımda dolduğunu görebiliyorum. UpperCaseUnderscoreStrategy.translate() örneğinde bir kesme noktası belirlerseniz, orada durmaz; bu nedenle, geri kalanı şablonunun onu çağıramayacağı açıktır. – Ezward

+0

Bir MappingJackson2HttpMessageConverter'ın messageConverters listesinden seçilmesinin hata ayıklamasını görebiliyorum. Daha fazla ObjectMapper izledim ve ObjectMapper.getDeserializationConfig() tarafından döndürülen DeserializationConfig öğesinin _propertyNameStrategy değeri null olduğunu görebiliyorum, bu yüzden şimdiye kadar yaptığımız her şey serileştirme boru hattına girmemiş. – Ezward

+0

Tamam, bunu anladım. Cevabınız çok yardımcı oldu. Düşük seviyeli kodumun her aramada RestTemplate'i yenilediğini öğrendim, böylece yapılandırılan şablon göz ardı edildi. Bir kez geri kalanı şablonumu düşük seviyeme otomatik olarak değiştirdiğimde, her şey işe yaradı. Şimdi beklendiği gibi çağrılan translate() yöntemini görüyorum. Yardım ettiğin için teşekkür ederim. – Ezward