converting images to base64 and sending as json - java

I am trying to convert images i have to base64 then send them as part of a JSON string and all is going ok except when I have 2 images. What happens is i only get the 2nd image twice in the JSON and on the server side but Im failing to see why this is happening..
Here is my code:
JSONObject jsonPhotos = new JSONObject();
if (photos != null) {
try {
JSONArray jsonObj = new JSONArray(photos);
for (int i = 0; i < jsonObj.length(); i++) {
JSONObject c = jsonObj.getJSONObject(i);
String imageUrl = c.getString("url");
System.out.println( "each urls: " + imageUrl );
String cap = c.getString("caption");
//get to base64
Bitmap bm = BitmapFactory.decodeFile(imageUrl);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 10, baos); //bm is the bitmap object
byte[] b = baos.toByteArray();
String encodedString = Base64.encodeToString(b, Base64.DEFAULT);
jsonPhotos.put( "imageData", encodedString);
jsonPhotos.put( "caption", cap);
claim.accumulate( "photos", jsonPhotos);
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
}
in my log each url is different. but when it gets put into the json the base64 encoded strings are the same.

Create a new jsonPhotos item on every iteration of the loop.
What's happening is that you create a single JSON object before the loop starts, and then you are continually updating it's "itemData" through every iteration of the loop.
I suspect that "claim.accumulate" is holding on to a reference of the JSONObject passed into it instead of making a deep copy. This should fix it.
if (photos != null) {
try {
JSONArray jsonObj = new JSONArray(photos);
for (int i = 0; i < jsonObj.length(); i++) {
...
JSONObject jsonPhotos = new JSONObject(); // add this line here
jsonPhotos.put( "imageData", encodedString);
jsonPhotos.put( "caption", cap);
claim.accumulate( "photos", jsonPhotos);
}

Related

JSONException on trying to get a value from Json to String

I'm trying to get 2 values from Wikipedia with the next API link:
https://en.wikipedia.org/w/api.php?action=query&generator=random&grnnamespace=0&prop=pageimages&format=json&pithumbsize=500&utf8
because its generated by random, sometimes it doesn't return one of the values I need, but I will solve this later, currently I'm having a problem with accessing the two values I need in the Json, "title" and "source"
The returned Json is like this:
{"batchcomplete":"","continue":{"grncontinue":"0.360395277951|0.360395626487|10429617|0","continue":"grncontinue||"},"query":{"pages":{"38690716":{"pageid":38690716,"ns":0,"title":"Alaine Chartrand","thumbnail":{"source":"https://upload.wikimedia.org/wikipedia/commons/d/d4/Alaine_Chartrand.jpg","width":267,"height":400},"pageimage":"Alaine_Chartrand.jpg"}}}}
this is the code, can anybody figure out why does it go to JSONException?
String API = "https://en.wikipedia.org/w/api.php?action=query&generator=random&grnnamespace=0&prop=pageimages&format=json&pithumbsize=500&utf8";
//open connection with wikipedia.
HttpURLConnection httpcon = (HttpURLConnection) new URL(API).openConnection();
//read all the input from wikipedia.
BufferedReader in = new BufferedReader(new InputStreamReader(httpcon.getInputStream()));
String responseSB = in.lines().collect(Collectors.joining());
in.close();
JSONObject incomingJSON = new JSONObject(responseSB);
//crashes here
String mTitle = incomingJSON.getString("title");
String mUrl = incomingJSON.getString("source");
If you notice the JSON it is randomly generated but with specific format
Case 1
{
"batchcomplete": "",
"continue": {
"grncontinue": "0.720220803439|0.720221273467|12887566|0",
"continue": "grncontinue||"
},
"query": {
"pages": {
"4897672": {
"pageid": 4897672,
"ns": 0,
"title": "New Hope, Sunnyvale, Texas"
}
}
}
}
query and pages were always existed, and in pages the key is always randomly generate, so it is Map<String, JSONObject> map of String key and JSONObject as value, Then you need to get the title value from map values
String API = "https://en.wikipedia.org/w/api.php?action=query&generator=random&grnnamespace=0&prop=pageimages&format=json&pithumbsize=500&utf8";
//open connection with wikipedia.
HttpURLConnection httpcon = (HttpURLConnection) new URL(API).openConnection();
//read all the input from wikipedia.
BufferedReader in = new BufferedReader(new InputStreamReader(httpcon.getInputStream()));
String responseSB = in.lines().collect(Collectors.joining());
in.close();
JSONObject incomingJSON = new JSONObject(responseSB);
Map<String,JSONObject> map = (Map<String, JSONObject>) incomingJSON.getJSONObject("query").getJSONObject("pages");
map.forEach((k,v)->System.out.println(" The key is : "+k+" the title is : "+v.getString("title")));
Case 2 With source
{
"batchcomplete": "",
"continue": {
"grncontinue": "0.165621850014|0.165622038679|37982311|0",
"continue": "grncontinue||"
},
"query": {
"pages": {
"57529788": {
"pageid": 57529788,
"ns": 0,
"title": "Model Store",
"thumbnail": {
"source": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/23/Australia_New_South_Wales_relief_location_map.png/500px-Australia_New_South_Wales_relief_location_map.png",
"width": 500,
"height": 443
},
"pageimage": "Australia_New_South_Wales_relief_location_map.png"
}
}
}
}
So source may not present in every response, handle with try catch
String API = "https://en.wikipedia.org/w/api.php?action=query&generator=random&grnnamespace=0&prop=pageimages&format=json&pithumbsize=500&utf8";
//open connection with wikipedia.
HttpURLConnection httpcon = (HttpURLConnection) new URL(API).openConnection();
//read all the input from wikipedia.
BufferedReader in = new BufferedReader(new InputStreamReader(httpcon.getInputStream()));
String responseSB = in.lines().collect(Collectors.joining());
in.close();
JSONObject incomingJSON = new JSONObject(responseSB);
Map<String,JSONObject> map = (Map<String, JSONObject>) incomingJSON.getJSONObject("query").getJSONObject("pages");
map.forEach((k,v)->{
System.out.println(" The key is : "+k+" the title is : "+v.getString("title"));
//use try catch to get source because you will not get the same response every time
String source = v.getJSONObject("thumbnail").getString("source");
});
}
You can't get title and source directly from JSON response because it has to contain multiple inner objects. Below is the code snap for reading title and source.
// new code
JSONObject incomingJSON = new JSONObject(responseSB);
JSONObject innerObject = incomingJSON.getJsonObject("query").getJsonObject("pages").getJsonObject("38690716");
String mTitle= innerObject.getString("title");
String mUrl= innerObject.getJsonObject("thumbnail").getString("source");
//crashes here
String mTitle = incomingJSON.getString("title");
String mUrl = incomingJSON.getString("source");
try this...
JSONObject incomingJSON = new JSONObject(responseSB);
JSONObject TitleObjects = incomingJSON.getJSONObject("query");
JSONObject j_Objects_01 = TitleObjects.getJSONObject("pages");
JSONObject j_Objects_02 = j_Objects_01.getJSONObject("38690716");
String mTitle = j_Objects_02.getString("title");
JSONObject j_Objects_03 = j_Objects_02.getJSONObject("thumbnail");
String mUrl = j_Objects_03.getString("source");
You should be aware that the page id will change and the thumbnail is optional.
// new code
JSONObject incomingJSON = new JSONObject(responseSB);
JSONObject pages = incomingJSON.getJSONObject("query").getJSONObject("pages");
Iterator<String> it = pages.keys();
while(it.hasNext()) {
JSONObject page = pages.getJSONObject(it.next());
String mTitle= page.getString("title");
if(page.keySet().contains("thumbnail")) {
String mUrl= page.getJSONObject("thumbnail").getString("source");
}
}
So because the ID kept changing, I've decided to go from another approach.
I've used the following code:
Pattern p = Pattern.compile("\"source\":\"(.*?)\",\"width");
Matcher m = p.matcher(responseSB);
if (m.find()) {
url = m.group(1);
}
p = Pattern.compile("\"title\":(.*?)\",\"thumbnail");
m = p.matcher(responseSB);
if (m.find()) {
description = m.group(1);
}

How do i get, modify and post a json object?

as mentioned in my older topic 3 days ago - Last Topic
i got a json response and changed it to a string. The Json Response represents an User-Object. Within the User-Object i wanted to search for a specific project and delete it. After that, i want to post it again via HttpPost.
private static String getContent(HttpResponse response) {
HttpEntity entity = response.getEntity();
if (entity == null) return null;
BufferedReader reader;
try {
reader = new BufferedReader(new InputStreamReader(entity.getContent()));
String line = reader.readLine();
reader.close();
return line;
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
String StringResponse = getContent(JsonResponse);
JSONObject jsonObject = new JSONObject(StringResponse);
JSONArray ProjectsArray= jsonObject.getJSONArray("projects");
Searching for a specific project by saving the attributes in a JsonArray.
ArrayList<Integer> indexesToRemove = new ArrayList<Integer>();
for (int i = 0; i < projectsArray.length; i++) {
JSONObject current = projectsArray.get(i);
if (current.get("projectKey") == "**ProjectName**") {
indexesToRemove.add(i);
}
}
Deleting the project...
for (int i = indexesToRemove.size()-1; i>=0; i--)
{
projectsArray.remove(indexesToRemove.get(i));
}
That works perfect and my searched project is deleted. But the problem is, that i want to post the modified UserObject/String again via HttpPost. And my deleted project is just in my JsonArray "projectsArray" and not in my string from the beginning. I can't post "projectsArray"....
HttpPost UserChange = new HttpPost (TestUserURL+user); //TODO:
UserChange.setHeader("Accept", "application/json");
UserChange.setHeader("Content-type", "application/json");
params = new StringEntity("ModifiedJsonString", HTTP.UTF_8); // How do i get the complete Json string?
UserChange.setEntity(params);
HttpResponse UserChangeResponse = httpclient.execute(UserChange);
HttpEntity entity2 = UserChangeResponse.getEntity();
if (entity2 != null) {
entity2.consumeContent();
}
I need the "ModifiedJsonString", which includes the complete json file from the beginning.
params = new StringEntity(ModifiedJsonString, HTTP.UTF_8);
Best Regards
The following code removes one of the selected project.
String jsonString = "{ \"account\": \"Kpatrick\", \"firstname\": \"Patrick\", \"instances\": [ { \"id\": \"packerer-pool\", \"key\": \"packerer-pool123\", \"userAccount\": \"kpatrick\", \"firstname\": \"Patrick\", \"lastname\": \"Schmidt\" } ], \"projects\": [ { \"id\": \"packerer-projectPool\", \"projectKey\": \"projectPool-Pool\", \"cqprojectName\": \"xxxxx\" }, { \"id\": \"packerer-secondproject\", \"projectKey\": \"projectPool-Pool2\", \"cqprojectName\": \"xxxx\" }, { \"id\": \"packerer-thirdproject\", \"projectKey\": \"projectPool-Pool3\", \"cqprojectName\": \"xxxx\" } ], \"clients\": [], \"dbid\": 76864576, \"version\": 1, \"id\": \"dbpack21\"}";
JSONParser parser = new JSONParser();
JSONObject jsonObject = (JSONObject) parser.parse(jsonString);
ArrayList<String> listOfNodes = new ArrayList<String>();
JSONArray projectArray = (JSONArray) jsonObject.get("projects");
int len = projectArray.size();
if (projectArray != null) {
for (int i = 0; i < len; i++) {
String projectId = ((JSONObject) projectArray.get(i)).get("projectKey").toString();
if (!projectId.equals("projectPool-Pool2")) {
listOfNodes.add(projectArray.get(i).toString());
}
}
}
// Remove the element from arraylist
// Recreate JSON Array
JSONArray jsArray = new JSONArray();
jsArray.addAll(listOfNodes);
jsonObject.remove(projectArray);
jsonObject.put("projects", listOfNodes);
System.out.println(jsonObject.toString());
This for example , prints the following JSON string removing one of the projects.
Once you have this , you can then use this to create a StringEntity and then use it in HTTPPost calls. Hope it helps

How to reduce the time for sending data to remote server?

E.g. there are 10MB data stored in my tablet. The data has a list structure. Each entry in the list is about 3500 Bytes.
Currently, I send one entry each time with the following codes:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(ipport+ phpHandler);
HttpResponse response = null;
try {
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "utf-8"));
response = httpclient.execute(httppost);
} catch (UnsupportedEncodingException e) {
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
But to send this 10MB data, it took a long time. Each sending of an entry takes about 1 second.
Any solution to improve the efficiency?
You can build a JSON string object which contains all the entities and then compress it with gzip or any other compression scheme.
The benefit of building a JSON object is you can transmit all the objects as one request, instead of sending it separately. This would eliminate the latency of establishing a new connection everytime.
// your data list = listData
JSONArray newArray = new JSONArray();
for (int i = 0, lsize = listData.size(); i < lsize; i++) {
try {
newArray.put(i, listData.get(i));
} catch (JSONException e) {
e.printStackTrace();
}
}
This code would build a JSONArray with all the elements in the listData (it should be a list of strings)
now you can easily convert the JSONArray to a string using
newArray.toString()
Now you can send this JSON string over the network, and you can easily deserialize a JSON object in any server side language.
As for Gzip compression, you might want to look at this link
Here is a question on SO about sending GZip compressed data over HTTP in android
GZip POST request with HTTPClient in Java
I am agreeing with the answer of #Ahmed. you better use jSON string object then compress using gzip libray.
for JSON there are lots of helpful tutorials. following link is really helpful
http://www.vogella.com/articles/AndroidJSON/article.html
here you can see the simple way to write json
public void writeJSON() {
JSONObject object = new JSONObject();
try {
object.put("name", "Jack Hack");
object.put("score", new Integer(200));
object.put("current", new Double(152.32));
object.put("nickname", "Hacker");
} catch (JSONException e) {
e.printStackTrace();
}
}
and to compress and decompress using gzip Here i am adding some sample codes from the answer https://stackoverflow.com/a/6718707/931982
public static byte[] compress(String string) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream(string.length());
GZIPOutputStream gos = new GZIPOutputStream(os);
gos.write(string.getBytes());
gos.close();
byte[] compressed = os.toByteArray();
os.close();
return compressed;
}
public static String decompress(byte[] compressed) throws IOException {
final int BUFFER_SIZE = 32;
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
StringBuilder string = new StringBuilder();
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
string.append(new String(data, 0, bytesRead));
}
gis.close();
is.close();
return string.toString();
}

HttpURLConection - JSON Response isn't Complete

I am trying to send a request to the Grooveshark API using POST Payload and their requested methods, and I have found a problem. Allow me to show you my code first.
public void getResponse() throws Exception
{
if(service.equals("Grooveshark")) link += getHmacMD5(privateGroovesharkKey, jsonInfo.toString());
if(requestedMethod.equals("GET")) infoURL = new URL(link+arguments);
else infoURL = new URL(link);
HttpURLConnection connection = (HttpURLConnection) infoURL.openConnection();
connection.setRequestMethod(requestedMethod);
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
if(service.equals("Grooveshark"))
{
connection.setRequestProperty("Content-Type","application/json");
OutputStream output = connection.getOutputStream();
output.write(jsonInfo.toString().getBytes());
}
else if(requestedMethod.equals("POST") || requestedMethod.equals("PUT"))
{
OutputStream output = connection.getOutputStream();
output.write(arguments.getBytes());
}
connection.connect();
BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null)
sb.append(line).append('\n');
setJsonResult(sb.toString());
System.out.println(jsonResult);
jsonFinal = new JSONObject(jsonResult);
connection.disconnect();
}
I have got that code up here in my project, and I can successfully send requested to any API Webservice that uses JSON in their responses. Now there's only a problem: In Android, it does not give me the WHOLE answer. I've tried running the code on a separate Java (no Android) project, and I get the following output. Although, if I run it on Android, the Log shows me the following:
{"header":{"hostname":"RHL073"},"result":{"songs":[{"SongID":5443351,"SongName":"??????\u00b7???? (FINAL FANTASY XII????)","ArtistID":713,"ArtistName":"Final Fantasy","AlbumID":898007,"AlbumName":"Final Fantasy XII Original Soundtrack","CoverArtFilename":"","Popularity":1214500005,"IsLowBitrateAvailable":tr
And it stops on that tr. Has it anything to do with the parsing of the file that I actually apply afterwards? I don't think it is, but just in case, here it is [This is how I call the search, JSONHandler being the object that contains the code provided above]:
public void performSearch() throws Exception
{
JSONObject search = new JSONObject();
search.put("method", method);
JSONObject header = new JSONObject();
header.put("wsKey", key);
JSONObject parameters = new JSONObject();
parameters.put("query", getSearchQuery());
parameters.put("country", "Portugal");
parameters.put("limit", limit);
parameters.put("offset", "");
search.put("header", header);
search.put("parameters", parameters);
JSONHandler jsonHandler = new JSONHandler(link, search, "Grooveshark", "POST", "");
JSONObject finalResult = jsonHandler.getJsonFinal();
JSONArray songs = finalResult.getJSONObject("result").getJSONArray("songs");
ArrayList<Result> allResults = new ArrayList<Result>();
for(int i = 0; i < songs.length(); i++)
{
JSONObject inner = (JSONObject) songs.get(i);
String name = inner.getString("SongName");
int ID = inner.getInt("SongID");
String artist = inner.getString("ArtistName");
Result res = new Result(name, artist, ID);
res.setAlbumName(inner.getString("AlbumName"));
boolean low = inner.getBoolean("IsLowBitrateAvailable");
int bit = 0;
if(low) bit = 1;
else bit = 0;
res.setIsLowBitRateAvailable(bit);
}
setResults(allResults);
}
As you can clearly see, I am using the json.org library. I really don't understand what's the problem here. Has anyone got any idea as to why?

How can i do a http get request in Blackberry

i have to do a http GET request on the URL http://api.twitter.com/1/users/show.json?screen_name=Kaka and i will get a JSON object, but i don't know how i have to do it.
Anyone could help me?
Thanks you.
This BlackBerry code sample shows how you do that
Or, From another fairly simple example, that uses the org.json.me package added to BlackBerry Java 6.0:
HttpConnection conn = null;
InputStream in = null;
ByteArrayOutputStream out = null;
try {
String url = "http://api.twitter.com/1/users/show.json?screen_name=Kaka";
conn = (HttpConnection) Connector.open(url, Connector.READ);
conn.setRequestMethod(HttpConnection.GET);
int code = conn.getResponseCode();
if (code == HttpConnection.HTTP_OK) {
in = conn.openInputStream();
out = new ByteArrayOutputStream();
byte[] buffer = new byte[in.available()];
int len = 0;
while ((len = in.read(buffer)) > 0) {
out.write(buffer);
}
out.flush();
String response = new String(out.toByteArray());
JSONObject resObject = new JSONObject(response);
String key = resObject.getString("Insert Json Key");
Vector resultsVector = new Vector();
JSONArray jsonArray = resObject.getJSONArray("Insert Json Array Key");
if (jsonArray.length() > 0) {
for (int i = 0; i < jsonArray.length();i++) {
Vector elementsVector = new Vector();
JSONObject jsonObj = jsonArray.getJSONObject(i);
elementsVector.addElement(jsonObj.getString("Insert Json Array Element Key1"));
elementsVector.addElement(jsonObj.getString("Insert Json Array Element Key2"));
resultsVector.addElement(elementsVector);
}
}
}
} catch (Exception e) {
Dialog.alert(e.getMessage());
} finally {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
if (conn != null) {
conn.close();
}
}
Obviously, in the second example, you have to insert the names of the JSON keys that your JSON data actually uses (left as an exercise for the poster). Also, you'll probably know something about how the JSON objects are structured, as objects, and arrays, etc. So, your code for unpacking the JSON data into JSONObjects and JSONArrays may look a little different than above, depending on the structure of your own JSON data.

Categories