简体   繁体   English

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

[英]How to serialize complex Json object to QueryString for HTTP Get using Jackson?

Say that I have following objects: 说我有以下对象:

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

Obviously when I request JSON of this with Jackson I get something like: 显然,当我向杰克逊请求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}

However what I need for QueryString is that top property pairs are converted to Key=Value& format, so something like: 但是,对于QueryString我需要的是将顶级属性对转换为Key = Value&格式,因此类似:

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

Plus of course MyPerson=[This_Part_Needs_To_Be_Url_Encoded]. 另外当然还有MyPerson = [This_Part_Needs_To_Be_Url_Encoded]。

Is there any generic method in Jackson that would do this for me automatically? 杰克逊中有任何通用方法可以自动为我执行此操作吗? Or will I be forced to come up with something my own? 还是我会被迫提出自己的想法? Some String replacement regex? 一些字符串替换正则表达式? Any ideas? 有任何想法吗?

[Edit] NOTE: I misunderstood the question. [编辑]注意:我误解了这个问题。 My answer below answers how to parse the JSON and get a Java object. 我在下面的答案回答了如何解析JSON并获取Java对象。 You wanted to get the Key value pairs where JSON is the value for the object. 您想获取Key值对,其中JSON是对象的值。 The below answer will not answer that question. 以下答案将不会回答该问题。 Sorry for the confusion. 对困惑感到抱歉。

You can fix this issue by using Jackson annotations to the java model and adding a "type" to the JSON object. 您可以通过在Java模型中使用Jackson批注并向JSON对象添加“类型”来解决此问题。 You might want to research it for your purposes but here is an example from some code I have done in the past. 您可能想针对您的目的进行研究,但这是我过去所做的一些代码中的一个示例。

public class Requirement {
  private String title;
  private String reqId;

  @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type")
  @JsonSubTypes({
      @JsonSubTypes.Type(value=CountRequirementList.class, name="COUNT"),
      @JsonSubTypes.Type(value=AndRequirementList.class, name="AND"),
      @JsonSubTypes.Type(value=OrRequirementList.class, name="OR")
  })
  private List<RequirementList>  fulfillments;

where the baseObject is the RequirementList and the class names are types of the requirements list. 其中baseObjectRequirementList ,而类名是requirements列表的类型。 To make things easier going back and forth from JSON, it is sometimes convenient to just add a type to the object. 为了使从JSON来回转换变得更容易,有时只需将类型添加到对象中便很方便。 I have included more code below in case it helps. 如果有帮助,我在下面添加了更多代码。 (note: I did not include all the getters and setters that are needed for Jackson) (注意:我没有包括杰克逊所需的所有吸气剂和吸气剂)

public abstract class RequirementList {
  private LogicType type;
  private String id;
  private String title;
  private String description;
  protected float requiredCount; //For count type subclass. Designed to be count of credits
  private List<Object> fulfillments;
}



public class OrRequirementList extends RequirementList {

  public OrRequirementList() {
    super();
    super.setType(LogicType.OR);
  }
}

See my answer for this question How to serialize ANY Object into a URI? 请参阅我对这个问题的答案如何将ANY对象序列化为URI? . You have to add only URL encoding to my solution. 您只需将URL编码添加到我的解决方案中。 For example you can use UrlEncoder#encode(String s, String enc) method. 例如,您可以使用UrlEncoder#encode(String s, String enc)方法。

OK, 好,

Here is the holder object: 这是持有人对象:

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

Here is how I initialize it: 这是我如何初始化它:

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

And finally the method that makes this happen: 最后是实现此目的的方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM