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}
。如果它是一个简单的类型,如原语或字符串
,请直接输入。用&
连接所有字段。是的,似乎这就是我要做的,因为正则表达式的家伙像往常一样脾气暴躁……只要我这样做,就会为其他人发布代码。