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'}]