Parse the body of a POST into a java object using a spark

I migrated from spring to light back, and now I'm fixated on something basic.

When I make a POST request sending data in the body, I want to return the JAVA object to the controller.

In spring, I used

@RequestBody User user 

And it was "filled" automatically.

Now using spark I have a method:

 request.body(); 

But this gives me a serialized string like this:

id=7&name=Pablo+Mat%C3%ADas&lastname=Gomez&githubUsername=pablomatiasgomez

So how can I get a User DTO?

Of course, the User class has properties

  • ID
  • name
  • Lastname
  • githubUsername
+6
source share
2 answers

AFAIK, Spark does not offer this feature. When I used it for a small pet project, I wrote some small utility methods for parsing a URL encoded string in 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 + '\'' + '}'; } } 

Running this Test class will output the following to the console:

  User {id = 7, name = 'Pablo Matías', lastname = 'Gomez', githubUsername = 'pablomatiasgomez'} 

Note that this also works when a User has a nested structure, say, Address , which consists of several other fields. jus separate the fields with "." in the following way:

 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 + '\'' + '}'; } } 

which will print:

  User {
   id = 7
   name = 'Pablo Matías'
   lastname = 'Gomez'
   githubUsername = 'pablomatiasgomez'
   address = Address {street = 'Coolsingel', number = '42a', city = 'Rotterdam'}
 } 

EDIT

And if the payload contains a list, say User s, you can do something like this:

 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 + '\'' + '}'; } } 

which will print:

  single user -> User {id = 7, name = 'Pablo Matías'}
 list of users ->: [User {id = 7, name = 'Pablo Matías'}, User {id = 42, name = 'Bart'}] 
+6
source

I found an easier way that doesn't include URL encoding.

On the client, turn your javascript object into a JSON string and set the request parameter for it (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 }); 

Then in 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. 
+2
source

Source: https://habr.com/ru/post/981571/


All Articles