extract image name from URL java - java

http://m.people.com/img/ic?width=474&height=269&fsize=999000&format=jpg&url=http%3A%2F%2Fimg2.timeinc.net%2Fpeople%2Fi%2F2011%2Fnews%2F110425%2Fgwyneth-paltrow-300.jpg
This is my url.How can I extract image name Fgwyneth-paltrow-300.jpg from the URL in java.
Thanks

First we want to decode the URL and get the url parameter. We can do that using BalusC's great code for parsing query Strings. Then we just have to split that URL by / and take the last part.
String url ="http://m.people.com/img/ic?width=474&height=269&fsize=999000&format=jpg&url=http%3A%2F%2Fimg2.timeinc.net%2Fpeople%2Fi%2F2011%2Fnews%2F110425%2Fgwyneth-paltrow-300.jpg";
Map<String, List<String>> params = new HashMap<String, List<String>>();
String[] urlParts = url.split("\\?");
if (urlParts.length > 1) {
String query = urlParts[1];
for (String param : query.split("&")) {
String[] pair = param.split("=");
String key;
try
{
key = URLDecoder.decode(pair[0], "UTF-8");
} catch (UnsupportedEncodingException e)
{
key = URLDecoder.decode(pair[0]);
}
String value;
try
{
value = URLDecoder.decode(pair[1], "UTF-8");
} catch (UnsupportedEncodingException e)
{
value = URLDecoder.decode(pair[1]);
}
List<String> values = params.get(key);
if (values == null) {
values = new ArrayList<String>();
params.put(key, values);
}
values.add(value);
}
}
String img = params.get("url").get(0);
String[] parts = img.split("/");
String imgName = parts[parts.length - 1];
System.out.println(imgName);

Related

read json with timestamps as jsonobject keys

I am trying to log weather data for a university hydrological project using java.
The data is formated as a json file in 5 minute intervals for the last 24 hours in the following way (example):
{
"1482439800":{
"hu":92,
"te":-2.9,
"dp":-4.5,
"pr":1028.4,
"pa":null,
"ws":1.4,
"wd":180
},
"1482440100":{
"hu":92,
"te":-2.9,
"dp":-4.5,
"pr":1028.4,
"pa":null,
"ws":1.4,
"wd":180
}
}
I have already tried to use the following code to access data from the json file:
private static String readUrl(String urlString) throws Exception {
BufferedReader reader = null;
try {
URL url = new URL(urlString);
reader = new BufferedReader(new InputStreamReader(url.openStream()));
StringBuffer buffer = new StringBuffer();
int read;
char[] chars = new char[1024];
while ((read = reader.read(chars)) != -1)
buffer.append(chars, 0, read);
return buffer.toString();
} finally {
if (reader != null)
reader.close();
}
}
public static Object[][] getstation1(){
Object[][] data = null;
try {
JSONObject json = new JSONObject(readUrl("http://netzwerk.wetter.com/api/stationdata/14091/24/"));
Iterator keys = json.keys();
while (keys.hasNext()) {
Object key = keys.next();
JSONObject value = json.getJSONObject((String) key);
double hu = value.getDouble("hu");
System.out.println(hu);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
This was somewhat successful as it returned data for humidity (hu) but in a seemingly random order.
Now for my question: How do I read the times and return them alongside the corresponding weather data from newest to oldest inside the Object[][]?
Any help is appreciated.
Thank you.
A sorted map would be more appropriate than an Object[][].
Quickly:
TreeMap<String, Object> sorted = new TreeMap<>(json.toMap());
But that will sort alphanumerically (probably fine in your case as the timestamps are all the same length).
You could do a little more work to sort the results into a typed map:
TreeMap<Date, Map<String, Double>> byDate = json.toMap().entrySet().stream()
.collect(Collectors.toMap(
e -> new Date(Long.valueOf(e.getKey()) * 1000),
e -> (Map) e.getValue(),
(a, b) -> {throw new IllegalArgumentException("Duplicate key " + a);},
TreeMap::new
));
If you really need an Object[][] you can remap your data once it's sorted:
Object[][] data = sorted.entrySet().stream().map(e -> new Object[] {e.getKey(), e.getValue()}).toArray(Object[][]::new);
Or consider using an object mapper like jackson or gson.
Thanks for the answer but in the end I decided to go a slightly simpler route.
I retrieved all the key names, sorted them and then read the corresponding data key by key. And as I was getting frequent errors because of data being null I added protection for that as well (I need them as actual numbers).
public static Object[][] getstation1(){
Object[][] data = null;
try {
JSONObject json = new JSONObject(readUrl("http://netzwerk.wetter.com/api/stationdata/14091/2/"));
System.out.println("Fetching "+"http://netzwerk.wetter.com/api/stationdata/14091/2/");
String[] times = json.getNames(json);
Arrays.sort(times);
data = new Object[times.length][8];
for (int i = 0; i < times.length; i++){
Date temp = new Date((long)Integer.parseInt(times[i])*1000);
data[i][0] = temp;
if (json.getJSONObject(times[i]).isNull("hu")){
data[i][1] = 0;
} else {
data[i][1] = json.getJSONObject(times[i]).getDouble("hu");
}
if (json.getJSONObject(times[i]).isNull("te")){
data[i][2] = 0;
} else {
data[i][2] = json.getJSONObject(times[i]).getDouble("te");
}
if (json.getJSONObject(times[i]).isNull("dp")){
data[i][3] = 0;
} else {
data[i][3] = json.getJSONObject(times[i]).getDouble("dp");
}
if (json.getJSONObject(times[i]).isNull("pr")){
data[i][4] = 0;
} else {
data[i][4] = json.getJSONObject(times[i]).getDouble("pr");
}
if (json.getJSONObject(times[i]).isNull("pa")){
data[i][5] = 0;
} else {
data[i][5] = json.getJSONObject(times[i]).getDouble("pa");
}
if (json.getJSONObject(times[i]).isNull("ws")){
data[i][6] = 0;
} else {
data[i][6] = json.getJSONObject(times[i]).getDouble("ws");
}
if (json.getJSONObject(times[i]).isNull("wd")){
data[i][7] = 0;
} else {
data[i][7] = json.getJSONObject(times[i]).getDouble("wd");
}
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return data;
}

Parse String to get grouped parameters

My String looks like this
http://localhost:8080/HospitalServer/files/file?id=34&firstname=alex&lastname=ozouf&age=33&firstname=kevin&lastname=gerfild&age=27
I use this code to parse the parameters
final Map<String, List<String>> query_pairs = new LinkedHashMap<String, List<String>>();
final String[] pairs = query.split("&");
for (String pair : pairs) {
final int idx = pair.indexOf("=");
final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), "UTF-8") : pair;
if (!query_pairs.containsKey(key)) {
query_pairs.put(key, new LinkedList<String>());
}
final String value = idx > 0 && pair.length() > idx + 1 ? URLDecoder.decode(pair.substring(idx + 1), "UTF-8") : null;
query_pairs.get(key).add(value);
}
System.out.println(query_pairs);
The result is
{id=[34], firstname=[alex, kevin], lastname=[ozouf, gerfild], age=[33, 27]}
The result is not too bad but I want to group the parameters by person.
{id=[34], 1=[alex,ozouf,33 ], 2=[kevin, gerfild,27]}
I can create it from the previous result but I have the feeling that the job is done twice. What do you think I shall do ?
Here's how you can do it without using any library:
import java.util.Map;
import java.util.HashMap;
public class MyUrlParser {
private static final String SEPARATOR = ",";
public static void main(String[] args) {
final String URL = "http://localhost:8080/HospitalServer/files/file?id=34&firstname=alex&lastname=ozouf&age=33&firstname=kevin&lastname=gerfild&age=27";
MyUrlParser mup = new MyUrlParser();
try {
Map<String, String> parsed = mup.parse(URL);
System.out.println(parsed);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
public Map<String, String> parse(String url) throws Exception {
Map<String, String> retMap = new HashMap<>();
int queryStringPos = url.indexOf("?");
if (-1 == queryStringPos) {
throw new Exception("Invalid URL");
}
String queryString = url.substring(queryStringPos + 1);
String[] parameters = queryString.split("&");
if (parameters.length > 0) {
retMap.put("id", parameters[0]);
int personCounter = 0;
for (int minSize = 4; minSize <= parameters.length; minSize += 3) {
StringBuilder person = new StringBuilder();
person.append(parameters[minSize-3]);
person.append(SEPARATOR);
person.append(parameters[minSize-2]);
person.append(SEPARATOR);
person.append(parameters[minSize-1]);
personCounter++;
retMap.put("person" + personCounter, person.toString());
}
}
return retMap;
}
}

CSV is not getting read properly in java using csvreader

This is my code. I am not able to write it back to a csv. I have figured out that the problem is with the header matching in the if loop. The values are being read correctly nut the if loop is not getting satisfied when the headers are getting matched. Any help is much appreciated. Thanks.
public class FactsChecker {
public static void main(String[] args) {
run();
}
static void run()
{
Map <String,String> csvMap = new HashMap<String,String>();
String csvPath = "resource/Sample.csv";
String outputPath = "resource/Output.csv";
String[] headers;
try{
CsvReader csvreader = new CsvReader("resource/Sample.csv");
csvreader.readHeaders();
headers = csvreader.getHeaders();
String[] values;
String key = null;
String value = null;
while (csvreader.readRecord()){`
values = csvreader.getValues();
System.out.println(headers[0]);
for (int i = 0; i < headers.length; i++) {
if (headers[i].equals("FCT_NAME")) {
key = values[i];
}
if (headers[i].equals("FCT_TYPE")) {
value = values[i];
}
}
csvMap.put(key,value);
}
for (Map.Entry<String, String> entry : csvMap.entrySet())
{
System.out.println(entry.getKey() + "/" + entry.getValue());
}
Map<String,Entry> entryMap= new HashMap<String, Entry>();
for (String factKey:csvMap.keySet()){
Entry entry = new Entry();
entry.setFactName(factKey);
String factType = csvMap.get(factKey);
System.out.println(factKey);
entry.setFactType(factType);
entryMap.put(factKey, entry);
}
CsvWriter writer = new CsvWriter(outputPath);
for(String key1 : entryMap.keySet()){
Entry entry = entryMap.get(key1);
writer.writeRecord(new String[]{entry.getFactName(),entry.getFactType()});
}
writer.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
try using contains instead of equals in case there is trailing or leading white space
I also faced the same issue .Try the below. Just remove this appended character from your header when you read it from csv and then compare.
if(headers[i].startswith("\uFEFF"){
headers[i].replace("\uFEFF","");
}

How to extract parameters from a given url

In Java I have:
String params = "depCity=PAR&roomType=D&depCity=NYC";
I want to get values of depCity parameters (PAR,NYC).
So I created regex:
String regex = "depCity=([^&]+)";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(params);
m.find() is returning false. m.groups() is returning IllegalArgumentException.
What am I doing wrong?
It doesn't have to be regex. Since I think there's no standard method to handle this thing, I'm using something that I copied from somewhere (and perhaps modified a bit):
public static Map<String, List<String>> getQueryParams(String url) {
try {
Map<String, List<String>> params = new HashMap<String, List<String>>();
String[] urlParts = url.split("\\?");
if (urlParts.length > 1) {
String query = urlParts[1];
for (String param : query.split("&")) {
String[] pair = param.split("=");
String key = URLDecoder.decode(pair[0], "UTF-8");
String value = "";
if (pair.length > 1) {
value = URLDecoder.decode(pair[1], "UTF-8");
}
List<String> values = params.get(key);
if (values == null) {
values = new ArrayList<String>();
params.put(key, values);
}
values.add(value);
}
}
return params;
} catch (UnsupportedEncodingException ex) {
throw new AssertionError(ex);
}
}
So, when you call it, you will get all parameters and their values. The method handles multi-valued params, hence the List<String> rather than String, and in your case you'll need to get the first list element.
Not sure how you used find and group, but this works fine:
String params = "depCity=PAR&roomType=D&depCity=NYC";
try {
Pattern p = Pattern.compile("depCity=([^&]+)");
Matcher m = p.matcher(params);
while (m.find()) {
System.out.println(m.group());
}
} catch (PatternSyntaxException ex) {
// error handling
}
However, If you only want the values, not the key depCity= then you can either use m.group(1) or use a regex with lookarounds:
Pattern p = Pattern.compile("(?<=depCity=).*?(?=&|$)");
It works in the same Java code as above. It tries to find a start position right after depCity=. Then matches anything but as little as possible until it reaches a point facing & or end of input.
I have three solutions, the third one is an improved version of Bozho's.
First, if you don't want to write stuff yourself and simply use a lib, then use Apache's httpcomponents lib's URIBuilder class: http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/utils/URIBuilder.html
new URIBuilder("http://...").getQueryParams()...
Second:
// overwrites duplicates
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
public static Map<String, String> readParamsIntoMap(String url, String charset) throws URISyntaxException {
Map<String, String> params = new HashMap<>();
List<NameValuePair> result = URLEncodedUtils.parse(new URI(url), charset);
for (NameValuePair nvp : result) {
params.put(nvp.getName(), nvp.getValue());
}
return params;
}
Third:
public static Map<String, List<String>> getQueryParams(String url) throws UnsupportedEncodingException {
Map<String, List<String>> params = new HashMap<String, List<String>>();
String[] urlParts = url.split("\\?");
if (urlParts.length < 2) {
return params;
}
String query = urlParts[1];
for (String param : query.split("&")) {
String[] pair = param.split("=");
String key = URLDecoder.decode(pair[0], "UTF-8");
String value = "";
if (pair.length > 1) {
value = URLDecoder.decode(pair[1], "UTF-8");
}
// skip ?& and &&
if ("".equals(key) && pair.length == 1) {
continue;
}
List<String> values = params.get(key);
if (values == null) {
values = new ArrayList<String>();
params.put(key, values);
}
values.add(value);
}
return params;
}
If you are developing an Android application, try this:
String yourParam = null;
Uri uri = Uri.parse(url);
try {
yourParam = URLDecoder.decode(uri.getQueryParameter(PARAM_NAME), "UTF-8");
} catch (UnsupportedEncodingException exception) {
exception.printStackTrace();
}
If spring-web is present on classpath, UriComponentsBuilder can be used.
MultiValueMap<String, String> queryParams =
UriComponentsBuilder.fromUriString(url).build().getQueryParams();
Simple Solution create the map out of all param name and values and use it :).
import org.apache.commons.lang3.StringUtils;
public String splitURL(String url, String parameter){
HashMap<String, String> urlMap=new HashMap<String, String>();
String queryString=StringUtils.substringAfter(url,"?");
for(String param : queryString.split("&")){
urlMap.put(StringUtils.substringBefore(param, "="),StringUtils.substringAfter(param, "="));
}
return urlMap.get(parameter);
}
same but with jsonobject:
public static JSONObject getQueryParams2(String url) {
JSONObject json = new JSONObject();
try {
String[] urlParts = url.split("\\?");
JSONArray array = new JSONArray();
if (urlParts.length > 1) {
String query = urlParts[1];
for (String param : query.split("&")) {
String[] pair = param.split("=");
String key = URLDecoder.decode(pair[0], "UTF-8");
String value = "";
if (pair.length > 1) {
value = URLDecoder.decode(pair[1], "UTF-8");
if(json.has(key)) {
array = json.getJSONArray(key);
array.put(value);
json.put(key, array);
array = new JSONArray();
} else {
array.put(value);
json.put(key, array);
array = new JSONArray();
}
}
}
}
return json;
} catch (Exception ex) {
throw new AssertionError(ex);
}
}

Is there any Java equivalent of PHP's http_build_query function?

I have a Map with my data and want to build a query string with it, just like I would with http_build_query on PHP. I'm not sure if this code is the best implementation of it or if I'm forgetting something?
public String toQueryString(Map<?, ?> data) throws UnsupportedEncodingException {
StringBuffer queryString = new StringBuffer();
for (Entry<?, ?> pair : data.entrySet()) {
queryString.append ( URLEncoder.encode ( (String) pair.getKey (), "UTF-8" ) + "=" );
queryString.append ( URLEncoder.encode ( (String) pair.getValue (), "UTF-8" ) + "&" );
}
if (queryString.length () > 0) {
queryString.deleteCharAt ( queryString.length () - 1 );
}
return queryString.toString ();
}
look at the QueryStringBuilder class and its test class :
private String httpBuildQuery(Map<String, String> data)
throws UnsupportedEncodingException {
QueryStringBuilder builder = new QueryStringBuilder();
for (Entry<String, String> pair : data.entrySet()) {
builder.addQueryParameter(pair.getKey(), pair.getValue());
}
return builder.encode("UTF-8");
}
The true power of PHP http_build_query function is its ability to get associative array and translate it into URL string. The following code do similar thing and it allows url params to be constructed as multi level Map that include nested Map and Collections.With some more work this a support for Array can also be added.
Test methods are shown below.
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
/**
* Class: URLBuilder
* User: Gilad Tiram
* Date: 6/12/13
* Time: 4:02 PM
* <p/>
* <p/>
* Utility that helps to build URL String
*/
public class URLBuilder {
/**
* Build URL string from Map of params. Nested Map and Collection is also supported
*
* #param params Map of params for constructing the URL Query String
* #param encoding encoding type. If not set the "UTF-8" is selected by default
* #return String of type key=value&...key=value
* #throws java.io.UnsupportedEncodingException
* if encoding isnot supported
*/
public static String httpBuildQuery(Map<String, Object> params, String encoding) {
if (isEmpty(encoding)) {
encoding = "UTF-8";
}
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, Object> entry : params.entrySet()) {
if (sb.length() > 0) {
sb.append('&');
}
String name = entry.getKey();
Object value = entry.getValue();
if (value instanceof Map) {
List<String> baseParam = new ArrayList<String>();
baseParam.add(name);
String str = buildUrlFromMap(baseParam, (Map) value, encoding);
sb.append(str);
} else if (value instanceof Collection) {
List<String> baseParam = new ArrayList<String>();
baseParam.add(name);
String str = buildUrlFromCollection(baseParam, (Collection) value, encoding);
sb.append(str);
} else {
sb.append(encodeParam(name));
sb.append("=");
sb.append(encodeParam(value));
}
}
return sb.toString();
}
private static String buildUrlFromMap(List<String> baseParam, Map<Object, Object> map, String encoding) {
StringBuilder sb = new StringBuilder();
String token;
//Build string of first level - related with params of provided Map
for (Map.Entry<Object, Object> entry : map.entrySet()) {
if (sb.length() > 0) {
sb.append('&');
}
String name = String.valueOf(entry.getKey());
Object value = entry.getValue();
if (value instanceof Map) {
List<String> baseParam2 = new ArrayList<String>(baseParam);
baseParam2.add(name);
String str = buildUrlFromMap(baseParam2, (Map) value, encoding);
sb.append(str);
} else if (value instanceof List) {
List<String> baseParam2 = new ArrayList<String>(baseParam);
baseParam2.add(name);
String str = buildUrlFromCollection(baseParam2, (List) value, encoding);
sb.append(str);
} else {
token = getBaseParamString(baseParam) + "[" + name + "]=" + encodeParam(value);
sb.append(token);
}
}
return sb.toString();
}
private static String buildUrlFromCollection(List<String> baseParam, Collection coll, String encoding) {
StringBuilder sb = new StringBuilder();
String token;
if (!(coll instanceof List)) {
coll = new ArrayList(coll);
}
List arrColl = (List) coll;
//Build string of first level - related with params of provided Map
for (int i = 0; i < arrColl.size(); i++) {
if (sb.length() > 0) {
sb.append('&');
}
Object value = (Object) arrColl.get(i);
if (value instanceof Map) {
List<String> baseParam2 = new ArrayList<String>(baseParam);
baseParam2.add(String.valueOf(i));
String str = buildUrlFromMap(baseParam2, (Map) value, encoding);
sb.append(str);
} else if (value instanceof List) {
List<String> baseParam2 = new ArrayList<String>(baseParam);
baseParam2.add(String.valueOf(i));
String str = buildUrlFromCollection(baseParam2, (List) value, encoding);
sb.append(str);
} else {
token = getBaseParamString(baseParam) + "[" + i + "]=" + encodeParam(value);
sb.append(token);
}
}
return sb.toString();
}
private static String getBaseParamString(List<String> baseParam) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < baseParam.size(); i++) {
String s = baseParam.get(i);
if (i == 0) {
sb.append(s);
} else {
sb.append("[" + s + "]");
}
}
return sb.toString();
}
/**
* Check if String is either empty or null
*
* #param str string to check
* #return true if string is empty. Else return false
*/
public static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}
private static String encodeParam(Object param) {
try {
return URLEncoder.encode(String.valueOf(param), "UTF-8");
} catch (UnsupportedEncodingException e) {
return URLEncoder.encode(String.valueOf(param));
}
}
/* ========================================================================= */
/* Test functions */
/* ========================================================================= */
public static void main(String[] args) {
//basicTest();
//testWithMap();
//testWithList();
//testWithNestedMap();
//testWithNestedList();
testCompound();
}
private static void basicTest() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
params.put("a", "1");
params.put("b", "2");
params.put("c", "3");
System.out.println(httpBuildQuery(params, "UTF-8"));
}
private static void testWithMap() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
params.put("a", "1");
params.put("b", "2");
Map<String, Object> cParams = new LinkedHashMap<String, Object>();
cParams.put("c1", "c1val");
cParams.put("c2", "c2val");
params.put("c", cParams);
System.out.println(httpBuildQuery(params, "UTF-8"));
}
private static void testWithNestedMap() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
params.put("a", "1");
params.put("b", "2");
Map<String, Object> cParamsLevel1 = new LinkedHashMap<String, Object>();
cParamsLevel1.put("cL1-1", "cLevel1-1val");
cParamsLevel1.put("cL1-2", "cLevel1-2val");
Map<String, Object> cParamsLevel2 = new LinkedHashMap<String, Object>();
cParamsLevel2.put("cL2-1", "cLevel2-1val");
cParamsLevel2.put("cL2-2", "cLevel2-2val");
cParamsLevel1.put("cL1-3", cParamsLevel2);
params.put("c", cParamsLevel1);
System.out.println(httpBuildQuery(params, "UTF-8"));
}
private static void testWithList() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
params.put("a", "1");
params.put("b", "2");
List<Object> cParams = new ArrayList<Object>();
cParams.add("c1val");
cParams.add("c2val");
params.put("c", cParams);
System.out.println(httpBuildQuery(params, "UTF-8"));
}
private static void testWithNestedList() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
params.put("a", "1");
params.put("b", "2");
List<Object> cParamsLevel1 = new ArrayList<Object>();
cParamsLevel1.add("cL1-val1");
cParamsLevel1.add("cL12-val2");
List<Object> cParamsLevel2 = new ArrayList<Object>();
cParamsLevel2.add("cL2-val1");
cParamsLevel2.add("cL2-val2");
cParamsLevel1.add(cParamsLevel2);
params.put("c", cParamsLevel1);
System.out.println(httpBuildQuery(params, "UTF-8"));
}
private static void testCompound() {
Map<String, Object> params = new LinkedHashMap<String, Object>();
//flat
params.put("a", "1");
params.put("b", "2");
//Map level 1
Map<String, Object> cParamsLevel1 = new LinkedHashMap<String, Object>();
cParamsLevel1.put("cL1-1", "cLevel1-1val");
cParamsLevel1.put("cL1-2", "cLevel1-2val");
//Map level 2
Map<String, Object> cParamsLevel2 = new LinkedHashMap<String, Object>();
cParamsLevel2.put("cL2-1", "cLevel2-1val");
cParamsLevel2.put("cL2-2", "cLevel2-2val");
cParamsLevel1.put("cL1-3", cParamsLevel2);
params.put("c", cParamsLevel1);
//List level 1
List<Object> dParamsLevel1 = new ArrayList<Object>();
dParamsLevel1.add("dL1-val1");
dParamsLevel1.add("dL12-val2");
//List level 2
List<Object> dParamsLevel2 = new ArrayList<Object>();
dParamsLevel2.add("dL2-val1");
dParamsLevel2.add("dL2-val2");
dParamsLevel1.add(dParamsLevel2);
params.put("d", dParamsLevel1);
System.out.println(httpBuildQuery(params, "UTF-8"));
}
}
For easy test of your results append the string resulted by tests as query String of real url that point to this PHP. Example
http://localhost/test.php?a=1&b=2&c[cL1-1]=cLevel1-1val&c[cL1-2]=cLevel1-2val&c[cL1-3][cL2-1]=cLevel2-1val&c[cL1-3][cL2-2]=cLevel2-2val&d[0]=dL1-val1&d[1]=dL12-val2&d[2][0]=dL2-val1&d[2][1]=dL2-val2
<?php
var_dump($_REQUEST);
?>
You'd probably want to check the "Accept" request header for the encodings supported by the client before forcing UTF-8 (even though it's probably the best choice).
This should be the easiest (and most reliable) solution:
protected static String httpBuildQuery(List<? extends NameValuePair> parameters, String encoding) {
return URLEncodedUtils.format(parameters, encoding).replace("*", "%2A");
}
Example usage:
List<NameValuePair> params = new ArrayList<NameValuePair>;
params.add(new BasicNameValuePair("key", "value"));
String queryString = httpBuildQuery(myParamList, "UTF-8");
Java not encoding the asterisk (+) while PHP does encode it %2A should be the only difference.
Looks OK, with these caveats:
make the parameter a Map<String, String> rather than casting key and value to String.
the hardcoded encoding looks suspicious. UTF-8 is not a given, it has to match the encoding defined in the header of the HTTP request. So the code should ensure that they do - at least define it as a constant somewhere and refer to that both here and wherever the request encoding is set.
Edit: It seems that I was wrong about the encoding; HTTP GET parameters are not subject to an encoding header, and did not traditionally have a well-defined encoding at all. RFC 3988 does seem to mandate UTF-8, but that sounds rather brittle to me, so unless you have tight control over the server and can ensure that it does indeed use UTF-8 as well, I'd use POST requests for any data that's not in the 7bit ASCII range.

Categories