在开发Java工程中,相信大家也遇到过接口的请求体过于复杂,用对象来映射,层层嵌套,不利于构造,不也利于维护,非常麻烦的情况,像这样:
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class AmRequestDTO {
private Session session = new Session();
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Session {
private String session_id;
private Integer processed_duration;
private Long timestamp;
private Integer wanted_sequence_id;
private String message;
private List sentence;
private Integer slice_time;
private Boolean is_silence;
private Float valid_speech_ratio;
private JSONObject extend;
...
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Sentence {
private Integer sentence_id;
private String post_processed_text;
private Float dirty_words_probability;
private List words;
...
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Words {
private Integer end_time;
private String text;
private Float confidence;
}
}
}
}
构造这样的请求体,对Java开发者来说,简直就是灾难。(为了方便映射RequestBody里面的字段,没有采用驼峰命名)
一、Java构造复杂结构体的救星:StringUtil.replace(CharSequence, Map)
此处的StringUtil不是常见的commons里面的,看POM:
com.github.ifeilong
feilong
3.0.10
为了大家查阅方便:
二、使用示例
以ES的RequestBody为例,此处只关注主要部分:
{
"filters": {
"and": [
{
"field": "floor_level_recall",
"action": "term",
"value": "${floorLevel}"
},
{
"field": "building_age_lower",
"action": "lte",
"value": ${buildingFinishYear}
},
{
"field": "build_area_lower",
"action": "lte",
"value": ${houseArea}
}
]
}
}
上面给定的字符串作为模板,使用 StringUtil.replace(CharSequence, Map) 解析匹配的变量:
@Test
public void testStringUtil() {
// 基准字符串
String strBenchmark = "{\"filters\":{\"and\":[{\"field\":\"floor_level_recall\",\"action\":\"term\",\"value\":\"${floorLevel}\"}," +
"{\"field\":\"building_age_lower\",\"action\":\"lte\",\"value\":${buildingFinishYear}}," +
"{\"field\":\"build_area_lower\",\"action\":\"lte\",\"value\":${houseArea}}]}}";
// 要匹配的值
Map map = new HashMap<>(3);
map.put("floorLevel", String.valueOf(19));
map.put("buildingFinishYear", String.valueOf(2015));
map.put("houseArea", String.valueOf(119.5));
System.out.println(StringUtil.replace(strBenchmark, map));
}
输出(格式化后):
{
"filters": {
"and": [
{
"field": "floor_level_recall",
"action": "term",
"value": "19"
},
{
"field": "building_age_lower",
"action": "lte",
"value": 2015
},
{
"field": "build_area_lower",
"action": "lte",
"value": 119.5
}
]
}
}
至此完成了这个结构体的构造,在实际使用过程中,对于复杂的结构体,都可以采用这种形式,使用fastjson的JSON.toJSONString()方法,先转为String,然后再构造,最后完成的某个字段或整个结构体以String或JSON的形式使用。以上是个人的解决办法,欢迎分享更好的办法,一起写出更优雅、简洁的代码!