OpenFeign / feign-form

Open Feign form encoder

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can you support the post form data of object type?

LIANGQI0811 opened this issue · comments

when I use it for spring boot of post form data.Map is too awkward to use.
I don't want to check that those are the default parameters or parameter names.
Will the object form be better?
For example:
class UserParams implements IParams{
int age;
String name;
UserParams(String name){
//age default is 1
this(name,1);
}
UserParams(String name,int age){
name=name;
age=age;
}
}

//then Realization IParams FormEncoder

Hi,

Thanks a lot for your interesting suggestion, as I understood clearly you would like to write something like:

  @RequestLine("POST /form")
  @Headers("Content-Type: application/x-www-form-urlencoded")
  Response form (MyIParamsPojo pojo);

instead of the way it works now:

  @RequestLine("POST /form")
  @Headers("Content-Type: application/x-www-form-urlencoded")
  Response form (@Param("key1") String key1, @Param("key2") String key2);

Unfortunately, I find it a little bit confusing for Feign and contracts (JAX-RS, Spring, and others, not only Feign-default as in the example above) users, who get used to working in one way - annotation based, don't you?

I re-write SpringFormEncoder to translate object into a Map. I know it's a little bit tricky, but it can help us to write a lot of @Param in our method parameter list. Below is a sample code:

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import java.lang.reflect.Type;
import java.util.Map;
import org.springframework.web.multipart.MultipartFile;

public class MyFormEncoder extends SpringFormEncoder {

  private final ObjectMapper mapper;

  public MyFormEncoder() {

    this(new Default(), null);
  }

  public MyFormEncoder(Encoder delegate) {
    this(delegate, null);
  }

  public MyFormEncoder(Encoder delegate, ObjectMapper mapper) {
    super(delegate);
    if (mapper == null) {
      mapper = new ObjectMapper();
    }
    this.mapper = mapper;
  }

  @Override
  public void encode(Object object, Type bodyType, RequestTemplate template)
      throws EncodeException {
    if (!bodyType.equals(MultipartFile.class) && !(object instanceof Map)) {
      Map<String, ?> requestBody = mapper.convertValue(object, new TypeReference<Map<String, ?>>() {
      });
      super.encode(requestBody, MAP_STRING_WILDCARD, template);
    } else {
      super.encode(object, bodyType, template);
    }
  }
}

@LIANGQI0811, @sgyyz, @shenliuyang
Guys, I have added this feature. See the README

This and other fixes will be available within the day in new version 3.5.0