使用 spark 将 POST 正文解析为 java 对象
Parse POST body to java object using spark
我不久前从 spring 迁移到 spark,现在我停留在一些基本的东西上。
当我发出 POST 请求在正文中发送数据时,我想让 JAVA 对象回到控制器中..
在spring我曾经做过
@RequestBody User user
它是自动 "filled"..
现在有了 spark,我有了方法:
request.body();
但这给了我一个像这样的序列化字符串:
id=7&name=Pablo+Mat%C3%ADas&lastname=Gomez&githubUsername=pablomatiasgomez
那么如何获取用户 DTO?
当然,用户 class 具有属性
- id
- 名字
- 姓氏
- github用户名
据我所知,Spark 不提供此功能。当我将它用于小型宠物项目时,我编写了一些小型实用方法来将 URL 编码的字符串解析为 POJO,如下所示:
import com.google.gson.Gson;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.LinkedHashMap;
import java.util.Map;
public class Test {
private static final Gson GSON = new Gson();
public static <T> T convert(String urlencoded, Class<T> type) {
try {
Map<String, Object> map = asMap(urlencoded);
String json = GSON.toJson(map);
return GSON.fromJson(json, type);
}
catch (Exception e) {
e.printStackTrace(); // TODO log
return null;
}
}
public static Map<String, Object> asMap(String urlencoded) throws UnsupportedEncodingException {
return asMap(urlencoded, "UTF-8");
}
@SuppressWarnings("unchecked")
public static Map<String, Object> asMap(String urlencoded, String encoding) throws UnsupportedEncodingException {
Map<String, Object> map = new LinkedHashMap<>();
for (String keyValue : urlencoded.trim().split("&")) {
String[] tokens = keyValue.trim().split("=");
String key = tokens[0];
String value = tokens.length == 1 ? null : URLDecoder.decode(tokens[1], encoding);
String[] keys = key.split("\.");
Map<String, Object> pointer = map;
for (int i = 0; i < keys.length - 1; i++) {
String currentKey = keys[i];
Map<String, Object> nested = (Map<String, Object>) pointer.get(keys[i]);
if (nested == null) {
nested = new LinkedHashMap<>();
}
pointer.put(currentKey, nested);
pointer = nested;
}
pointer.put(keys[keys.length - 1], value);
}
return map;
}
public static void main(String[] args) {
String payload = "id=7&name=Pablo+Mat%C3%ADas&lastname=Gomez&githubUsername=pablomatiasgomez";
User user = convert(payload, User.class);
System.out.println(user);
}
}
class User {
long id;
String name;
String lastname;
String githubUsername;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", lastname='" + lastname + '\'' +
", githubUsername='" + githubUsername + '\'' +
'}';
}
}
运行 此 Test
class 将在您的控制台上打印以下内容:
User{id=7, name='Pablo Matías', lastname='Gomez', githubUsername='pablomatiasgomez'}
请注意,当 User
中有嵌套结构时,这也适用,例如,由几个其他字段组成的 Address
。只需用 "."
分隔字段,如下所示:
public class Test {
// ... same code ...
public static void main(String[] args) {
String payload = "id=7&name=Pablo+Mat%C3%ADas&lastname=Gomez&githubUsername=pablomatiasgomez&" +
"address.street=Coolsingel&address.number=42a&address.city=Rotterdam";
User user = convert(payload, User.class);
System.out.println(user);
}
}
class User {
long id;
String name;
String lastname;
String githubUsername;
Address address;
@Override
public String toString() {
return "User{" +
"\n id=" + id +
"\n name='" + name + '\'' +
"\n lastname='" + lastname + '\'' +
"\n githubUsername='" + githubUsername + "'" +
"\n address=" + address + "\n" +
'}';
}
}
class Address {
String street;
String number;
String city;
@Override
public String toString() {
return "Address{" +
"street='" + street + '\'' +
", number='" + number + '\'' +
", city='" + city + '\'' +
'}';
}
}
这将打印:
User{
id=7
name='Pablo Matías'
lastname='Gomez'
githubUsername='pablomatiasgomez'
address=Address{street='Coolsingel', number='42a', city='Rotterdam'}
}
编辑
如果负载包含一个列表,比如 User
s,你可以这样做:
public class Test {
private static final Gson GSON = new Gson();
public static <T> T convert(String urlencoded, Type type) {
try {
Map<String, Object> map = asMap(urlencoded);
String json = GSON.toJson(containsList(map) ? map.values() : map);
return GSON.fromJson(json, type);
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static boolean containsList(Map<String, Object> map) {
return !map.isEmpty() && new ArrayList<>(map.keySet()).get(0).contains("[");
}
public static Map<String, Object> asMap(String urlencoded) throws UnsupportedEncodingException {
return asMap(urlencoded, "UTF-8");
}
@SuppressWarnings("unchecked")
public static Map<String, Object> asMap(String urlencoded, String encoding) throws UnsupportedEncodingException {
Map<String, Object> map = new LinkedHashMap<>();
for (String keyValue : urlencoded.trim().split("&")) {
String[] tokens = keyValue.trim().split("=");
String key = tokens[0];
String value = tokens.length == 1 ? null : URLDecoder.decode(tokens[1], encoding);
String[] keys = key.split("\.");
Map<String, Object> pointer = map;
for (int i = 0; i < keys.length - 1; i++) {
String currentKey = keys[i];
Map<String, Object> nested = (Map<String, Object>) pointer.get(keys[i]);
if (nested == null) {
nested = new LinkedHashMap<>();
}
pointer.put(currentKey, nested);
pointer = nested;
}
pointer.put(keys[keys.length - 1], value);
}
return map;
}
public static void main(String[] args) throws Exception {
String payload = "id=7&name=Pablo Mat%C3%ADas";
User user = convert(payload, User.class);
System.out.println("single user -> " + user);
payload = "users[0].id=7&users[0].name=Pablo Mat%C3%ADas&users[1].id=42&users[1].name=Bart";
List<User> users = convert(payload, new TypeToken<List<User>>(){}.getType());
System.out.println("list of users -> : " + users);
}
}
class User {
long id;
String name;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
这将打印:
single user -> User{id=7, name='Pablo Matías'}
list of users -> : [User{id=7, name='Pablo Matías'}, User{id=42, name='Bart'}]
我找到了一种更简单的方法,它不涉及 URL 编码。
在客户端,将您的 javascript 对象转换为 JSON 字符串并使用它设置查询参数 (yourObject):
var obj = null;
obj = {
yourObject: JSON.stringify(currentObject)
};
$.ajax({
type: "GET",
url: "saveAnObject",
data: obj,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
console.log('saveAnObject result: ' + data + ".");
},
error: function() {
},
cache: false
});
然后在 Spark 中:
get("/saveAnObject", (req, res) - > {
String yourObjectStr = "" + req.queryParams("yourObject");
// Convert the JSON string to a POJO obj
Gson gson = new GsonBuilder().create();
YourObject pojoObj = gson.fromJson(yourObjectStr , YourObject.class);
// do something with your pojoObj object.
我不久前从 spring 迁移到 spark,现在我停留在一些基本的东西上。
当我发出 POST 请求在正文中发送数据时,我想让 JAVA 对象回到控制器中..
在spring我曾经做过
@RequestBody User user
它是自动 "filled"..
现在有了 spark,我有了方法:
request.body();
但这给了我一个像这样的序列化字符串:
id=7&name=Pablo+Mat%C3%ADas&lastname=Gomez&githubUsername=pablomatiasgomez
那么如何获取用户 DTO?
当然,用户 class 具有属性
- id
- 名字
- 姓氏
- github用户名
据我所知,Spark 不提供此功能。当我将它用于小型宠物项目时,我编写了一些小型实用方法来将 URL 编码的字符串解析为 POJO,如下所示:
import com.google.gson.Gson;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.LinkedHashMap;
import java.util.Map;
public class Test {
private static final Gson GSON = new Gson();
public static <T> T convert(String urlencoded, Class<T> type) {
try {
Map<String, Object> map = asMap(urlencoded);
String json = GSON.toJson(map);
return GSON.fromJson(json, type);
}
catch (Exception e) {
e.printStackTrace(); // TODO log
return null;
}
}
public static Map<String, Object> asMap(String urlencoded) throws UnsupportedEncodingException {
return asMap(urlencoded, "UTF-8");
}
@SuppressWarnings("unchecked")
public static Map<String, Object> asMap(String urlencoded, String encoding) throws UnsupportedEncodingException {
Map<String, Object> map = new LinkedHashMap<>();
for (String keyValue : urlencoded.trim().split("&")) {
String[] tokens = keyValue.trim().split("=");
String key = tokens[0];
String value = tokens.length == 1 ? null : URLDecoder.decode(tokens[1], encoding);
String[] keys = key.split("\.");
Map<String, Object> pointer = map;
for (int i = 0; i < keys.length - 1; i++) {
String currentKey = keys[i];
Map<String, Object> nested = (Map<String, Object>) pointer.get(keys[i]);
if (nested == null) {
nested = new LinkedHashMap<>();
}
pointer.put(currentKey, nested);
pointer = nested;
}
pointer.put(keys[keys.length - 1], value);
}
return map;
}
public static void main(String[] args) {
String payload = "id=7&name=Pablo+Mat%C3%ADas&lastname=Gomez&githubUsername=pablomatiasgomez";
User user = convert(payload, User.class);
System.out.println(user);
}
}
class User {
long id;
String name;
String lastname;
String githubUsername;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", lastname='" + lastname + '\'' +
", githubUsername='" + githubUsername + '\'' +
'}';
}
}
运行 此 Test
class 将在您的控制台上打印以下内容:
User{id=7, name='Pablo Matías', lastname='Gomez', githubUsername='pablomatiasgomez'}
请注意,当 User
中有嵌套结构时,这也适用,例如,由几个其他字段组成的 Address
。只需用 "."
分隔字段,如下所示:
public class Test {
// ... same code ...
public static void main(String[] args) {
String payload = "id=7&name=Pablo+Mat%C3%ADas&lastname=Gomez&githubUsername=pablomatiasgomez&" +
"address.street=Coolsingel&address.number=42a&address.city=Rotterdam";
User user = convert(payload, User.class);
System.out.println(user);
}
}
class User {
long id;
String name;
String lastname;
String githubUsername;
Address address;
@Override
public String toString() {
return "User{" +
"\n id=" + id +
"\n name='" + name + '\'' +
"\n lastname='" + lastname + '\'' +
"\n githubUsername='" + githubUsername + "'" +
"\n address=" + address + "\n" +
'}';
}
}
class Address {
String street;
String number;
String city;
@Override
public String toString() {
return "Address{" +
"street='" + street + '\'' +
", number='" + number + '\'' +
", city='" + city + '\'' +
'}';
}
}
这将打印:
User{ id=7 name='Pablo Matías' lastname='Gomez' githubUsername='pablomatiasgomez' address=Address{street='Coolsingel', number='42a', city='Rotterdam'} }
编辑
如果负载包含一个列表,比如 User
s,你可以这样做:
public class Test {
private static final Gson GSON = new Gson();
public static <T> T convert(String urlencoded, Type type) {
try {
Map<String, Object> map = asMap(urlencoded);
String json = GSON.toJson(containsList(map) ? map.values() : map);
return GSON.fromJson(json, type);
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static boolean containsList(Map<String, Object> map) {
return !map.isEmpty() && new ArrayList<>(map.keySet()).get(0).contains("[");
}
public static Map<String, Object> asMap(String urlencoded) throws UnsupportedEncodingException {
return asMap(urlencoded, "UTF-8");
}
@SuppressWarnings("unchecked")
public static Map<String, Object> asMap(String urlencoded, String encoding) throws UnsupportedEncodingException {
Map<String, Object> map = new LinkedHashMap<>();
for (String keyValue : urlencoded.trim().split("&")) {
String[] tokens = keyValue.trim().split("=");
String key = tokens[0];
String value = tokens.length == 1 ? null : URLDecoder.decode(tokens[1], encoding);
String[] keys = key.split("\.");
Map<String, Object> pointer = map;
for (int i = 0; i < keys.length - 1; i++) {
String currentKey = keys[i];
Map<String, Object> nested = (Map<String, Object>) pointer.get(keys[i]);
if (nested == null) {
nested = new LinkedHashMap<>();
}
pointer.put(currentKey, nested);
pointer = nested;
}
pointer.put(keys[keys.length - 1], value);
}
return map;
}
public static void main(String[] args) throws Exception {
String payload = "id=7&name=Pablo Mat%C3%ADas";
User user = convert(payload, User.class);
System.out.println("single user -> " + user);
payload = "users[0].id=7&users[0].name=Pablo Mat%C3%ADas&users[1].id=42&users[1].name=Bart";
List<User> users = convert(payload, new TypeToken<List<User>>(){}.getType());
System.out.println("list of users -> : " + users);
}
}
class User {
long id;
String name;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
这将打印:
single user -> User{id=7, name='Pablo Matías'} list of users -> : [User{id=7, name='Pablo Matías'}, User{id=42, name='Bart'}]
我找到了一种更简单的方法,它不涉及 URL 编码。
在客户端,将您的 javascript 对象转换为 JSON 字符串并使用它设置查询参数 (yourObject):
var obj = null;
obj = {
yourObject: JSON.stringify(currentObject)
};
$.ajax({
type: "GET",
url: "saveAnObject",
data: obj,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
console.log('saveAnObject result: ' + data + ".");
},
error: function() {
},
cache: false
});
然后在 Spark 中:
get("/saveAnObject", (req, res) - > {
String yourObjectStr = "" + req.queryParams("yourObject");
// Convert the JSON string to a POJO obj
Gson gson = new GsonBuilder().create();
YourObject pojoObj = gson.fromJson(yourObjectStr , YourObject.class);
// do something with your pojoObj object.