Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用Jackson将复杂的Json对象序列化为HTTP Get的QueryString?_Java_Android_Regex_Json_Jackson - Fatal编程技术网

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

Java 如何使用Jackson将复杂的Json对象序列化为HTTP Get的QueryString?,java,android,regex,json,jackson,Java,Android,Regex,Json,Jackson,假设我有以下对象: public class ComplexJacksonObject extends BaseJsonObject { public int Start; public int Count; public Person MyPerson; public class Person extends BaseJsonObject { public String Firstname; public String Last

假设我有以下对象:

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;
    }
}
显然,当我向Jackson请求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}
MyPerson={"Firstname":"First","Lastname":"Last","Where":{"Street":"Street","Number":15}}&Count=1&Start=2
但是,我需要QueryString将顶级属性对转换为Key=Value&format,如下所示:

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}
MyPerson={"Firstname":"First","Lastname":"Last","Where":{"Street":"Street","Number":15}}&Count=1&Start=2
当然还有MyPerson=[这个部分需要进行Url编码]


在Jackson中是否有任何通用方法可以自动为我实现这一点?还是我会被迫提出我自己的东西?一些字符串替换正则表达式?有什么想法吗

[编辑]注意:我误解了这个问题。下面我的答案回答了如何解析JSON并获取Java对象。您希望获得键值对,其中JSON是对象的值。下面的答案不会回答这个问题。很抱歉给你带来了困惑

您可以通过对java模型使用Jackson注释并向JSON对象添加“类型”来解决此问题。您可能希望出于自己的目的对其进行研究,但这里是我在过去完成的一些代码中的一个示例

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;

请看我对这个问题的回答。您只需将URL编码添加到我的解决方案中。例如,您可以使用
urlcoder\encode(字符串s,字符串enc)
方法。

确定

以下是holder对象:

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扩展了BaseJsonObject{
公共int启动;
公共整数计数;
公众人物;
公共列表字符串;
公共类Person扩展BaseJsonObject{
公共字符串名;
公共字符串Lastname;
公共广播(如有);
}
公共类地址扩展BaseJsonObject{
公众街;;
公共整数;
}
}
以下是我如何初始化它:

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
ComplexJacksonObject cjo=新的ComplexJacksonObject();
cjo.Count=1;
cjo.Start=2;
cjo.Strings=newArrayList();
cjo.Strings.添加(“一”);
cjo.Strings.添加(“两个”);
cjo.MyPerson=cjo.newPerson();
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;
字符串结果=cjo.toQueryString();
//字符串=%5B%221%22%2C%222%22%5D和我的人=%7B名字%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;
    }
}
toQueryString()的公共字符串{
StringBuilder sb=新的StringBuilder();
for(字段:this.getClass().getDeclaredFields()){
如果(sb.length()>0){
某人附加(“&”);
}
类cls=field.getType().getSuperclass();
//序列化我的复杂对象-它们都继承自BaseJsonObject类
if(cls!=null&&cls.equals(BaseJsonObject.class)){
BaseJsonObject bjo=(BaseJsonObject)getFieldValue(field);
字符串str=toJson(bjo,true);
sb.append(field.getName()).append(“=”).append(Uri.encode(str));
} 
//序列化列表,它们都是列表
else if(field.getType().equals(List.class)){
List bjo=(List)getFieldValue(field);
字符串val=toJson(bjo,false);
sb.append(field.getName()).append(“=”).append(Uri.encode(val));
} 
//序列化简单字段
否则{
对象bjo=getFieldValue(字段);
字符串val=toJson(bjo,false).replaceAll(“^\”|\“$”,”);
sb.append(field.getName()).append(“=”).append(Uri.encode(val));
}
}
使某人返回字符串();
}
私有对象getFieldValue(字段){
试一试{
返回字段。获取(此);
}捕获(IllegalArgumentException e){
e、 printStackTrace();
}捕获(非法访问例外e){
e、 printStackTrace();
}
返回null;
}
私有静态ObjectMapper generateMapper(){
ObjectMapper om=新的ObjectMapper();
//configure(在未知属性上反序列化feature.FAIL,false);
om.setDateFormat(新的JacksonSimpleDateFormat());
返回om;
}
公共字符串toJson(){
试一试{
返回generateMapper().writeValueAsString(this);
}捕获(JsonProcessingException e){
e、 printStackTrace();
返回null;
}
}
公共字符串toJson(对象o,布尔值noQuoteProperties){
试一试{
ObjectMapper om=generateMapper();
if(noQuoteProperties){
com.configure(com.fasterxml.jackson.core.JsonGenerator.Feature.QUOTE_字段_名称,false);
configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW\u UNQUOTED\u FIELD\u NAMES,true);
}
返回om.writeValueAsString(o);
}捕获(JsonProcessingException e){
e、 printStackTrace();
返回null;
}
}

Jackson生成JSON。如果您只希望
Person
成为JSON,请将其传递给
ObjectMapper
,然后自己构建其余部分。您可能会发现此讨论很有用。@SotiriosDelimanolis是的,我可以非常轻松地手动构建请求,但我正在寻找通用的解决方案。我想也许我应该检测一下对象是特定类型,如果是,我将其解析为JSON,否则我只将其作为key=value对输出。知道我如何做到这一点(反射)吗?编辑:查看这一点:使用反射,只需获取所有声明的字段。根据序列化规则,如果是复杂类型,则使用JSON将其序列化,并将其作为
fieldName={json here}
。如果它是一个简单的类型,如原语或
字符串
,请直接输入。用
&
连接所有字段。是的,似乎这就是我要做的,因为正则表达式的家伙像往常一样脾气暴躁……只要我这样做,就会为其他人发布代码。