We are doing some integration towards a quite inconsistent (Zurmo-)REST API. The API only accepts urlencoded strings as its payload in the http posts, but it answers with JSON.
So as the documentation was very unclear on this we naturally thought we could post JSON to it, but this was not the case.
So now we have all our code generating JSON when we need to send it as x-www-form-urlencoded, is there any java library that can do a conversion from JSON to an urlencoded string?
We are currently using the org.json lib, but we can change it if there would be a need for it.
Example:
This JSON string:
{"data":{"description":"test","occurredOnDateTime":"2013-10-24 01:44:50"}}
Should be converted into this:
data%5Bdescription%5D=test&data%5BoccurredOnDateTime%5D=2013-10-24+01%3A44%3A50
Java code:
We translated rasmushaglunds javascript code to java and wrapped it, here is the result if anybody else stumbles upon this problem.
public static String jsonToURLEncoding(JSONObject json) {
String output = "";
String[] keys = JSONObject.getNames(json);
for (String currKey : keys)
output += jsonToURLEncodingAux(json.get(currKey), currKey);
return output.substring(0, output.length()-1);
}
private static String jsonToURLEncodingAux(Object json, String prefix) {
String output = "";
if (json instanceof JSONObject) {
JSONObject obj = (JSONObject)json;
String[] keys = JSONObject.getNames(obj);
for (String currKey : keys) {
String subPrefix = prefix + "[" + currKey + "]";
output += jsonToURLEncodingAux(obj.get(currKey), subPrefix);
}
} else if (json instanceof JSONArray) {
JSONArray jsonArr = (JSONArray) json;
int arrLen = jsonArr.length();
for (int i = 0; i < arrLen; i++) {
String subPrefix = prefix + "[" + i + "]";
Object child = jsonArr.get(i);
output += jsonToURLEncodingAux(child, subPrefix);
}
} else {
output = prefix + "=" + json.toString() + "&";
}
return output;
}
public static String objectToUrlEncodedString(Object object, Gson gson) {
return jsonToUrlEncodedString((JsonObject) new JsonParser().parse(gson.toJson(object)));
}
private static String jsonToUrlEncodedString(JsonObject jsonObject) {
return jsonToUrlEncodedString(jsonObject, "");
}
private static String jsonToUrlEncodedString(JsonObject jsonObject, String prefix) {
String urlString = "";
for (Map.Entry<String, JsonElement> item : jsonObject.entrySet()) {
if (item.getValue() != null && item.getValue().isJsonObject()) {
urlString += jsonToUrlEncodedString(
item.getValue().getAsJsonObject(),
prefix.isEmpty() ? item.getKey() : prefix + "[" + item.getKey() + "]"
);
} else {
urlString += prefix.isEmpty() ?
item.getKey() + "=" + item.getValue().getAsString() + "&" :
prefix + "[" + item.getKey() + "]=" + item.getValue().getAsString() + "&";
}
}
return urlString;
}
There is an easier way now, and that is to use the URLEncoder.encode method.
Import the URLEncoder package:
import java.net.URLEncoder;
and then:
URLEncoder.encode(objectMapper.writeValueAsString(<yourClass>), StandardCharsets.UTF_8.toString());
You can test your result here:
https://onlinejsontools.com/url-decode-json
As noted below, it's not a Java library but you should be able to translate it :)
Here's how you could do it in javascript:
var jsonArrayToUrl = function (obj, prefix) {
var urlString = "";
for (var key in obj) {
if (obj[key] !== null && typeof obj[key] == "object") {
prefix += "[" + key + "]";
urlString += jsonArrayToUrl(obj[key], prefix);
}else{
urlString += prefix + "[" + key + "]=" + obj[key] + "&";
}
}
return encodeURIComponent(urlString);
};
Then call it with
jsonArrayToUrl(test["data"], "data");
By the example string you gave above it returns
"data%5Bdescription%5D%3Dtest%26data%5BoccurredOnDateTime%5D%3D2013-10-24%2001%3A44%3A50%26"
It should work recursively on nested arrays. You might also consider writing a wrapper for the function so that you only need one argument.
Related
How can I check for an empty Optional array of strings in Java?
In the case is empty I would like to return a message.
#PostMapping("/users")
#ResponseBody
public String saveUsers(#RequestParam Optional<String>[] paramArray) {
System.out.println("param " + paramArray);
String msg = "";
int i = 0;
if (paramArray is empty) {
msg = "paramArray is empty";
} else {
for (Optional<String> paramArrayItem : paramArray) {
msg += "param[" + i + "]" + paramArrayItem + "\n";
i++;
}
}
return msg;
}
Optional<String>[] is an array of Optional<String> elements.
You'd rather want to have optional array of strings, so you need to change paramArray type to Optional<String[]>.
#PostMapping("/users")
#ResponseBody
public String saveUsers(#RequestParam Optional<String[]> paramArray) {
System.out.println("param " + paramArray);
String msg = "";
int i = 0;
if (paramArray.isEmpty()) {
msg = "paramArray is empty";
} else {
for (String paramArrayItem : paramArray.get()) {
msg += "param[" + i + "]" + paramArrayItem + "\n";
i++;
}
}
return msg;
}
I am able to update the value of jsonObject by using key name , here the method which I am using
private static JSONObject setValue(JSONObject json, String key, String newValue) throws JSONException {
Iterator<?> keys = json.keys();
while (keys.hasNext()) {
String k = (String) keys.next();
if (key.equals(k)) {
json.put(key, newValue);
}
Object value = json.opt(k);
if (value instanceof JSONObject) {
setValue((JSONObject) value, key, newValue);
}
}
return json;
}
But this is not working in case of JSONArray object , I tried surfing , tried some method but not able to get desire output , an sample request payload:
{
"sactions": [
{
"fund": "REAL",
"amount": {
"value": 130.24,
"curr": "RMB"
},
"type": "TD",
"desc": "TD",
"code": "PROMO",
"id": "deaedd69e3-6707-4b27-940a-39c3b64abdc7"
}
]
}
Looking an recursive method to update value for any given key.
This is what I tried , but did not work
public static JSONObject setProperty(JSONObject js1, String keys, String valueNew) throws JSONException {
String[] keyMain = keys.split("\\.");
for (String keym : keyMain) {
Iterator<?> iterator = js1.keys();
String key = null;
while (iterator.hasNext()) {
key = (String) iterator.next();
if ((js1.optJSONArray(key) == null) && (js1.optJSONObject(key) == null)) {
if ((key.equals(keym))) {
js1.put(key, valueNew);
return js1;
}
}
if (js1.optJSONObject(key) != null) {
if ((key.equals(keym))) {
js1 = js1.getJSONObject(key);
break;
}
}
if (js1.optJSONArray(key) != null) {
JSONArray jArray = js1.getJSONArray(key);
for (int i = 0; i < jArray.length(); i++) {
js1 = jArray.getJSONObject(i);
}
break;
}
}
}
return js1;
}
This is how I am using the method (Ceating request body using lombok and jakson)
ObjectMapper mapper = new ObjectMapper();
String.valueOf(setValue(new JSONObject(mapper.writeValueAsString(transferFund())),
field, " "))
Thanks in advance
You can utilize JsonPath jayway to save your time.
For example:
String jsonInput = "{\n" +
" \"sactions\": [\n" +
" {\n" +
" \"fund\": \"REAL\",\n" +
" \"amount\": {\n" +
" \"value\": 130.24,\n" +
" \"curr\": \"RMB\"\n" +
" },\n" +
" \"type\": \"TD\",\n" +
" \"desc\": \"TD\",\n" +
" \"code\": \"PROMO\",\n" +
" \"id\": \"deaedd69e3-6707-4b27-940a-39c3b64abdc7\"\n" +
" }\n" +
" ]\n" +
"}";
String newJson = JsonPath.parse(jsonInput).set("$..id", "test").jsonString();
System.out.println(newJson);
Given a sample JSON:
{
"hello" : "wolrd",
"arrayField" : ["one", "two", "three"],
"mapField" : {
"name" : "john",
"lastName" : "doe"
}
}
Is there a framework in Java to help me get the JSON path structure from the JSON tree? Something similar to this:
$.hello
$.arrayField[0]
$.arrayField[1]
$.arrayField[2]
$.mapField.name
$.mapField.lastName
EDIT:
I've already coded a first approach using fasterxml's Jackson. But I'd like to know if there's something more robust / flexible.
final JsonNode rootNode = mapper.readValue(jon, JsonNode.class);
printFieldKeys(rootNode, "$");
private static void printFieldKeys(JsonNode rootNode, String parent) {
final Iterator<Entry<String, JsonNode>> fieldIt = rootNode.fields();
while (fieldIt.hasNext()) {
final Entry<String, JsonNode> next = fieldIt.next();
final JsonNode value = next.getValue();
final String path = parent + "." + next.getKey();
if (value.isValueNode()) {
System.out.println(path + " = " + value.asText());
} else {
System.out.println(path);
}
if (value.isArray()) {
for (int i = 0; i < value.size(); i++) {
printFieldKeys(value.get(i), path + "[" + i + "]");
}
} else {
printFieldKeys(value, path);
}
}
}
Take a look at this library: https://github.com/jayway/JsonPath
I believe it does exactly what you want. :)
How can I split a flat string based on 0102**? string tokenizer is working for only **. Is there any way to split based on 0102**? Please suggest
Here is my complete method
private String handleCibil(InterfaceRequestVO ifmReqDto, String szExtIntType) throws MalformedURLException, org.apache.axis.AxisFault, RemoteException {
/* Declaration and initiliazation */
ConfVO confvo = ifmReqDto.getExtConfVo();
String szResponse = null;
String cibilResponse = null;
String errorResponse = null;
String endpointURL = null;
long timeOut = confvo.getBurMgr().getBurInfo(szExtIntType).getTimeOut();
endpointURL = formWebServiceURL(confvo, szExtIntType);
URL url = new URL(endpointURL);
log.debug("Input xml for cibil "+ifmReqDto.getIfmReqXML());
BasicHttpStub stub= new BasicHttpStub(url,new org.apache.axis.client.Service());
szResponse = stub.executeXMLString(ifmReqDto.getIfmReqXML());
//szResponse=szResponse.replaceAll("&", "&");
log.debug("szResponse "+szResponse);
/* Validate if the obtained response is as expected by IFM */
try {
extDao = new ExtInterfaceXMLTransDAO(ifmReqDto.getSemCallNo(), ifmReqDto.getIdService());
extDao.updateRqstRespXML10g(ifmReqDto.getInterfaceReqNum(), szResponse, GGIConstants.IFM_RESPONSE);
//log.debug("CIBIL_RESPONSE_XPATH " + GGIConstants.CIBIL_RESPONSE_XPATH);
Document xmlDocument = DocumentHelper.parseText(szResponse);
String xPath = GGIConstants.RESPONSE_XPATH;
List<Node> nodes = xmlDocument.selectNodes(xPath);
for (Node node : nodes) {
String keyValue = node.valueOf(GGIConstants.RESPONSE_XPATH_KEY);
// log.debug("keyValue : " + keyValue);
if (keyValue.equalsIgnoreCase(GGIConstants.RESPONSE_XPATH_KEY_VALUE)) {
// log.debug("node value : " + node.getText());
cibilResponse = node.getText();
}
}
log.debug("cibilResponse " + cibilResponse);
String errorResponseXPATH = GGIConstants.CIBIL_ERROR_RESPONSE_XPATH;
List<Node> errorResponseNode = xmlDocument.selectNodes(errorResponseXPATH);
for (Node node : errorResponseNode) {
errorResponse = node.getText();
}
log.debug("errorResponse " + errorResponse);
if(cibilResponse!=null && cibilResponse.length()>0)
{
StringTokenizer cibilResponseResults = new StringTokenizer(cibilResponse,"**");
String tempResponse="";
ArrayList probableMatchList = new ArrayList();
while (cibilResponseResults.hasMoreElements()) {
tempResponse = (String) cibilResponseResults.nextElement();
if(tempResponse.length()>=80)
{
String memberRefNo = tempResponse.substring(69, 80).replaceAll(" ", "");
log.debug("memberRefNo " + memberRefNo);
if (memberRefNo.length() > 0) {
if (Integer.parseInt(memberRefNo) > 0) {
cibilResponse = tempResponse;
cibilResponse = cibilResponse+"**";
}
else
{
probableMatchList.add(tempResponse+"**");
}
}
else
{
probableMatchList.add(tempResponse+"**");
}
}
else
{
cibilResponse = tempResponse+"**";
}
}
log.debug("After finding the Member reference number cibilResponse " + cibilResponse);
log.debug("After finding the Probable reference list " + probableMatchList);
// TKN 008
cibilResponse=StringEscapeUtils.unescapeXml(cibilResponse).replaceAll("[^\\x20-\\x7e]","");
ifmReqDto.setIfmTransformedResult(cibilResponse);
ifmReqDto.setProbableMatchList(probableMatchList);
}
if (errorResponse!=null && errorResponse.length()>0) {
throw new GenericInterfaceException(errorResponse
+ " for the seq_request " + ifmReqDto.getSeqRequest() + " Seq_Interface_req is >> "
+ ifmReqDto.getInterfaceReqNum(),
GGIConstants.SEND_REQUEST_CONSTANT + Strings.padStart(String.valueOf(ifmReqDto.getIdService()), 2, GGIConstants.DEFAULT_NUMBER_STRING)
+ GGIConstants.CIBIL_ERROR_CODE);
}
else if (cibilResponse==null || StringUtils.isEmpty(cibilResponse) ) {
throw new GenericInterfaceException("Cibil TUEF response is empty >> cibil Service "
+ "for the seq_request " + ifmReqDto.getSeqRequest() + "Seq_Interface_req is >> "
+ ifmReqDto.getInterfaceReqNum(),
GGIConstants.SEND_REQUEST_CONSTANT + Strings.padStart(String.valueOf(ifmReqDto.getIdService()), 2, GGIConstants.DEFAULT_NUMBER_STRING)
+ GGIConstants.INTERFACE_ERROR_RESPONSE);
}
/* Setting Instinct response to ifmReqDto object */
} catch (SQLException e) {
log.error("SQLException while connecting to DataBase. Exception message is ", e);
throw new GenericInterfaceException("SQLException >> Instinct Service "
+ "for the seq_request " + ifmReqDto.getSeqRequest() + "Seq_Interface_req is >> "
+ ifmReqDto.getInterfaceReqNum(),
GGIConstants.SEND_REQUEST_CONSTANT + Strings.padStart(String.valueOf(ifmReqDto.getIdService()), 2, GGIConstants.DEFAULT_NUMBER_STRING)
+ GGIConstants.DB_OPERATION_ERROR);
} catch (GenericInterfaceException exp) {
log.error("Exception occured while valid:", exp);
throw exp;
} catch (Exception exp) {
log.error("Exception occured while valid:", exp);
throw new GenericInterfaceException("GeneralException >> Instinct Service "
+ "for the seq_request " + ifmReqDto.getSeqRequest() + "Seq_Interface_req is >> "
+ ifmReqDto.getInterfaceReqNum(),
GGIConstants.SEND_REQUEST_CONSTANT + Strings.padStart(String.valueOf(ifmReqDto.getIdService()), 2, GGIConstants.DEFAULT_NUMBER_STRING)
+ GGIConstants.UNKNOWN_ERROR);
}
return szResponse;
}
I recommend checking out the Java documentation, it provides a really good reference to start with. The .split method uses a regex to split up a string based on a delimiter.
String[] tokens = myString.split("0102\\*\\*");
For now I suspect that you forgot to escape * in split regex.
Try maybe
String[] resutl = yourString.split("0102\\*\\*");
In case you want * to represent any character then use . instead of *
String[] resutl = yourString.split("0102..");
In case you want * to represent any digit use \\d instead
String[] resutl = yourString.split("0102\\d\\d");
String string = "blabla0102**dada";
String[] parts = string.split("0102\\*\\*");
String part1 = parts[0]; // blabla
String part2 = parts[1]; // dada
Here we have a String: "blabla0102**dada", we call it string. Every String object has a method split(), using this we can split a string on anything we desire.
Do you mean literally split by "0102**"? Couldn't you use regex for that?
String[] tokens = "My text 0102** hello!".split("0102\\*\\*");
System.out.println(tokens[0]);
System.out.println(tokens[1]);
I'm using android.util.Log
class Foo
{
private void boo()
{
// This is the basic log of android.
Log.i("tag", "Start");
}
}
I want the log should be printed [Foo::boo] Start.
Can I get the class and function name in Java? Then how do I wrap the code?
here
UPDATED
String tag = "[";
tag += this.getClass().toString();
tag += " :: ";
tag += Thread.currentThread().getStackTrace()[1].getMethodName().toString();
tag += "]";
Log.i(tag, "Message");
this.getClass().toString() will return class name as String
UPDATE
if function is static then use following code
String tag = "[";
tag += Thread.currentThread().getStackTrace()[1].getClassName().toString();
tag += " :: ";
tag += Thread.currentThread().getStackTrace()[1].getMethodName().toString();
tag += "]";
Log.i(tag, "Message");
Get The Current Class Name and Function Name :
Log.i(getFunctionName(), "Start");
private String getFunctionName()
{
StackTraceElement[] sts = Thread.currentThread().getStackTrace();
if(sts == null)
{
return null;
}
for(StackTraceElement st : sts)
{
if(st.isNativeMethod())
{
continue;
}
if(st.getClassName().equals(Thread.class.getName()))
{
continue;
}
if(st.getClassName().equals(this.getClass().getName()))
{
continue;
}
return mClassName + "[ " + Thread.currentThread().getName() + ": "
+ " " + st.getMethodName() + " ]";
}
return null;
}
You can use these methods of java.lang.Class class
getClass().getname() - to get the name of the class
getClass().getMethods() - to get the methods declared in that class.