小编典典

如何使用Jackson将复杂的Json对象序列化为QueryString for HTTP Get?

java

说我有以下对象:

public class ComplexJacksonObject extends BaseJsonObject {
    public int Start;
    public int Count;
    public Person MyPerson;

    public class Person extends BaseJsonObject {
        public String Firstname;
        public String Lastname;
        public Address Where;
    }

    public class Address extends BaseJsonObject {
        public String Street;
        public int Number;
    }
}

显然,当我向杰克逊请求JSON时,我得到如下信息:

public String toJson(ComplexJacksonObject obj) {
    try {
        return generateMapper().writeValueAsString(obj);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
        return null;
    }
}

// returned: {"MyPerson":{"Firstname":"First","Lastname":"Last","Where":{"Street":"Street","Number":15}},"Count":1,"Start":2}

但是,我对QueryString的需求是将顶级属性对转换为Key = Value&格式,因此类似:

MyPerson={"Firstname":"First","Lastname":"Last","Where":{"Street":"Street","Number":15}}&Count=1&Start=2

当然还有MyPerson = [This_Part_Needs_To_Be_Url_Encoded]。

杰克逊中有任何通用方法会自动为我执行此操作吗?还是我会被迫提出自己的想法?一些字符串替换正则表达式?有任何想法吗?


阅读 477

收藏
2020-11-30

共1个答案

小编典典

好,

这是持有人对象:

public class ComplexJacksonObject extends BaseJsonObject {
    public int Start;
    public int Count;
    public Person MyPerson;
    public List<String> Strings;

    public class Person extends BaseJsonObject {
        public String Firstname;
        public String Lastname;
        public Address Where;
    }

    public class Address extends BaseJsonObject {
        public String Street;
        public int Number;
    }
}

这是我如何初始化它:

ComplexJacksonObject cjo = new ComplexJacksonObject();
cjo.Count = 1;
cjo.Start = 2;
cjo.Strings = new ArrayList<String>();
cjo.Strings.add("One");
cjo.Strings.add("Two");

cjo.MyPerson = cjo.new Person();
cjo.MyPerson.Firstname = "Fi\",=[]{}rst";
cjo.MyPerson.Lastname = "Last";

cjo.MyPerson.Where = cjo.new Address();
cjo.MyPerson.Where.Street = "Street";
cjo.MyPerson.Where.Number = 15;

String result = cjo.toQueryString();        
// Strings=%5B%22One%22%2C%22Two%22%5D&MyPerson=%7BFirstname%3A"Fi%5C%5C%22%2C%3D%5B%5D%7B%7Drst"%2CLastname%3A%22Last%22%2CWhere%3A%7BStreet%3A%22Street%22%2CNumber%3A15%7D%7D&Start=2&Count=1

最后,使这种情况发生的方法:

public String toQueryString() {
    StringBuilder sb = new StringBuilder();
    for (Field field : this.getClass().getDeclaredFields()) {
        if (sb.length() > 0) {
            sb.append("&");
        }

        Class cls = field.getType().getSuperclass();
        // serializing my complex objects - they all inherit from BaseJsonObject class
        if (cls != null && cls.equals(BaseJsonObject.class)) {
            BaseJsonObject bjo = (BaseJsonObject) getFieldValue(field);
            String str = toJson(bjo, true);
            sb.append(field.getName()).append("=").append(Uri.encode(str));
        } 
        // serializing lists, they are all List<T>
        else if (field.getType().equals(List.class)) {
            List bjo = (List) getFieldValue(field);
            String val = toJson(bjo, false);
            sb.append(field.getName()).append("=").append(Uri.encode(val));
        } 
        // serializing simple fields
        else {
            Object bjo = getFieldValue(field);
            String val = toJson(bjo, false).replaceAll("^\"|\"$", "");
            sb.append(field.getName()).append("=").append(Uri.encode(val));
        }
    }

    return sb.toString();
}

private Object getFieldValue(Field field) {
    try {
        return field.get(this);
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }

    return null;
}

private static ObjectMapper generateMapper() {
    ObjectMapper om = new ObjectMapper();
    // om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    om.setDateFormat(new JacksonSimpleDateFormat());

    return om;
}

public String toJson() {
    try {
        return generateMapper().writeValueAsString(this);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
        return null;
    }
}

public String toJson(Object o, boolean noQuoteProperties) {
    try {
        ObjectMapper om = generateMapper();
        if (noQuoteProperties) {                
            om.configure(com.fasterxml.jackson.core.JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
            om.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);           
        }
        return om.writeValueAsString(o);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
        return null;
    }
}
2020-11-30