【问题标题】:groovy RESTClient json custom serializationgroovy RESTClient json 自定义序列化
【发布时间】:2014-05-19 12:11:54
【问题描述】:
class Account {
    Date dob=new Date();
}

import net.sf.json.JSON;
import groovyx.net.http.RESTClient;

    def rest=new RESTClient("http://localhost:9090/Rest/rest")
    def resp=rest.post(
        contentType: "application/json",
        body: account
        )

JSON 内容形成为

{"dob":{"date":19,"day":1,"hours":17,"minutes":34,"month":4,"seconds":44,"time":1400501084326,"timezoneOffset":-330,"year":114}}

如何为 Date 覆盖 JSON 序列化程序 Long(getTime())

【问题讨论】:

    标签: json groovy


    【解决方案1】:

    有点晚了,我认为这不是最干净的,但我希望它有所帮助。

    需要用您自己的 JSON 解析器替换“EncoderRegistry”。

    RESTClient restClient = new RESTClient( "http://myrest.com")
    EncoderRegistry encoderRegistry = restClient.getEncoder();
    encoderRegistry.putAt(groovyx.net.http.ContentType.JSON, {it ->
        def builder = new groovy.json.JsonBuilder();
        builder.content = it
        ByteArrayInputStream dataStreamed = new ByteArrayInputStream(builder.toString().getBytes(StandardCharsets.UTF_8))
        InputStreamEntity res = new InputStreamEntity(dataStreamed);
        res.setContentType(groovyx.net.http.ContentType.JSON.toString())
        res;
    })
    

    使用 JsonBuilder 而不是其余客户端的默认值,它使用标准格式发送日期:yyyy-MM-ddTHH:mm:ss+.sTZD

    那么你就可以照常使用restClient了:

     def response = restClient.post(
                path: path,
                headers: ["User-Agent": "UserAgent"],
                query: query,
                body: body,
                requestContentType: groovyx.net.http.ContentType.JSON
        )
    

    顺便说一句,如果要替换解析器,则需要替换“ParserRegistry”

     ParserRegistry parserRegistry = restClient.getParser()     
     parserRegistry.putAt(groovyx.net.http.ContentType.JSON,{HttpResponseDecorator resp ->
            def obj = null
            if (resp.status ==200){
                if(clazz != null){
                    String jsonString = IOUtils.toString(resp.getEntity().getContent(), "UTF-8");
                    obj = new ObjectMapper().readValue(jsonString,new TypeReference<MyObject>(){});
                }
                return obj
            }else{
                throw new Exception("No found")
            }
        })
    

    【讨论】:

      【解决方案2】:

      Iñaki 的回答有些不同。

      用 JsonGenerator 替换默认 JSON 编码器的示例。

      def generator = new groovy.json.JsonGenerator.Options()
          .excludeNulls()
          .addConverter(Instant) { Instant i ->
              i.toEpochMilli()
          }
          .build()
      
      restClient.getEncoder().putAt(groovyx.net.http.ContentType.JSON, {body ->
          StringEntity entity = new StringEntity(generator.toJson(body))
          entity.setContentType( groovyx.net.http.ContentType.JSON.toString() )
          return entity
      })
      

      用 ObjectMapper 替换 JSON 编码器和解析器的示例:

      import com.fasterxml.jackson.databind.DeserializationFeature
      import com.fasterxml.jackson.databind.ObjectMapper
      import com.fasterxml.jackson.databind.SerializationFeature
      import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
      import org.apache.http.entity.StringEntity
      
      ObjectMapper objectMapper = new ObjectMapper()
      objectMapper.registerModule(new JavaTimeModule())
      objectMapper.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
      objectMapper.disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)
      objectMapper.disable(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)
      
      restClient.getEncoder().putAt(groovyx.net.http.ContentType.JSON, {body ->
          StringEntity entity = new StringEntity(objectMapper.writeValueAsString(body))
          entity.setContentType( groovyx.net.http.ContentType.JSON.toString() )
          return entity
      })
      
      restClient.getParser().putAt(JSON, { resp ->
          return objectMapper.readValue(resp.entity.content, YourPojo.class)
      })
      

      【讨论】:

        【解决方案3】:

        可能不是最聪明的解决方案,但您可以从帐户对象中获取属性映射并更改date 键:

        import net.sf.json.*
        
        class Account {
          Date date = Date.parse("yyyy-MM-dd", '2014-05-01')
          String name
        }
        
        a = new Account(name: 'john doe')
        
        aMap = a.properties
        
        aMap.date = aMap.date.time
        
        json = JSONObject.fromObject(aMap)
        
        assert json.toString() == '{"date":1398913200000,"name":"john doe"}'
        

        【讨论】:

          【解决方案4】:

          您可以在 Bootstrap 文件中修改 marshaller,例如:

             class BootStrap {
          
              def init = {
                  servletContext ->
          
                  JSON.registerObjectMarshaller(Date) {
          
                      return it.time
                  }
              }
          }
          

          【讨论】:

          • 我的不是 grails 应用程序,它的 JSF 应用程序带有一些用 groovy 编写的 Spring 服务
          猜你喜欢
          • 2011-02-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-07
          相关资源
          最近更新 更多