I have stayed with the problem for more than 3 days of research but cant find any solvable solution. My android project makes a request to my gcloud functions and the function returns a string response with a String format:
[{"response": [{"Commission": 50, "Price": 0.5, "Quantity": "20"}, {"Commission": 50, "Quantity": 20, "Price": 1}, {"Quantity": 20, "Price": 10, "Commission": 50}], "code": 200}]
I was able to convert the string to JSON and retrieve the value of the "response" key.
try {
//convertion of response to json to fetch value
JSONObject jsonObj = new JSONObject("[{"response": [{"Commission": 50, "Price": 0.5, "Quantity": "20"}, {"Commission": 50, "Quantity": 20, "Price": 1}, {"Quantity": 20, "Price": 10, "Commission": 50}], "code": 200}]");
String code = jsonObj.getString("code");
final String Cod = code;
if (Cod.equals("200")){
String availableInv = jsonObj.getString("response");
availableInv = availableInv.replace("[", "");
availableInv = availableInv.replace("]", "");
String strng[] = availableInv.split("},");
for (String val:strng) {
int valLength = val.length();
if(!val.substring(valLength-1, valLength).contentEquals("}")) {
val +="}";
}
System.out.println(">>>>>>=====================response==========="+val);
JSONObject jsonObjInv = new JSONObject(val);
float price = Float.valueOf(jsonObjInv.getString("Price"));
float comission = Float.valueOf(jsonObjInv.getString("Commission"));
float quantity = Float.valueOf(jsonObjInv.getString("Quantity"));
myDataset.add(new InvestmentsModel(price,comission, quantity));
}
}
}
Now i want to be able to iterate through the list of the JSON object and fetch the keys and values.
When i run my solution i get the following error:
2020-03-24 16:17:55.235 4959-5006/com.example.SMS E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
Process: com.example.SMS, PID: 4959
java.util.regex.PatternSyntaxException: Syntax error in regexp pattern near index 1
},
^
at java.util.regex.Pattern.compileImpl(Native Method)
at java.util.regex.Pattern.compile(Pattern.java:1340)
at java.util.regex.Pattern.<init>(Pattern.java:1324)
at java.util.regex.Pattern.compile(Pattern.java:946)
at java.lang.String.split(String.java:2384)
at java.lang.String.split(String.java:2426)
at com.example.SMS.Fragment.investEarnFrag_1$5.onResponse(investEarnFrag_1.java:251)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:504)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Seems that you find your answer in the comments. However, I think there is some point which is worth to emphasize here.
First of all, since you already decided to serialize your raw json response to a java object, which is JSONObject in this case, there is no point to parse the rest of the string anymore. You should stick with one of the methodologies to keep it consistent. So, in this case the methodology should be either parsing the whole json string or using org.json features. In my personal opinion, you should keep using the org.json.
Using org.json
The response you shared is in form of array/list of object.
[{"response": [{"Commission": 50, "Price": 0.5, "Quantity": "20"}, {"Commission": 50, "Quantity": 20, "Price": 1}, {"Quantity": 20, "Price": 10, "Commission": 50}], "code": 200}]
Since we have array of objects, we should use JSONArray to keep our json in.
JSONArray jsonArray = new JSONArray("[{\"response\": [{\"Commission\": 50, \"Price\": 0.5, \"Quantity\": \"20\"}, {\"Commission\": 50, \"Quantity\": 20, \"Price\": 1}, {\"Quantity\": 20, \"Price\": 10, \"Commission\": 50}], \"code\": 200}]");
// just to exemplify we get the first element, this should be depending on the business logic
JSONObject jsonObj = (JSONObject) jsonArray.get(0);
Now, we have the inner object in our jsonObj variable, which is:
{
"response": [
{
"Commission": 50,
"Price": 0.5,
"Quantity": "20"
},
{
"Commission": 50,
"Quantity": 20,
"Price": 1
},
{
"Quantity": 20,
"Price": 10,
"Commission": 50
}
],
"code": 200
}
So, we can easily get on key response which will be againg an array of object. We can easily iterate on it.
Note that in json all keys are string while values can be string, numeric, booelan and object. For instance, status can be parsed as integer.
try {
//convertion of response to json to fetch value
JSONArray jsonArray = new JSONArray("[{\"response\": [{\"Commission\": 50, \"Price\": 0.5, \"Quantity\": \"20\"}, {\"Commission\": 50, \"Quantity\": 20, \"Price\": 1}, {\"Quantity\": 20, \"Price\": 10, \"Commission\": 50}], \"code\": 200}]");
JSONObject jsonObj = (JSONObject) jsonArray.get(0);
int code = jsonObj.getInt("code");
List<InvestmentsModel> myDataset = new ArrayList<>();
if (code == 200){
JSONArray availableInv = jsonObj.getJSONArray("response");
for (Object val: availableInv) {
JSONObject value = (JSONObject) val;
float price = value.getFloat("Price");
float comission = value.getFloat("Commission");
float quantity = value.getFloat("Quantity");
myDataset.add(new InvestmentsModel(price,comission, quantity));
}
}
} catch (Exception e ) {
// todo handle exception
}
This can be a more naive answer to your question than parsing the raw response.
Taking one step further
It seems that we already have model class for InvestmentsModel. The more elegant approach is to keep things in their own contexts and to create for pojos for responses.
Assumed we have such InvestmentsModel:
import com.fasterxml.jackson.annotation.JsonProperty;
public class InvestmentsModel {
#JsonProperty("Price")
private float price;
#JsonProperty("Commission")
private float comission;
#JsonProperty("Quantity")
private float quantity;
public InvestmentsModel() {
}
public InvestmentsModel(float price, float comission, float quantity) {
this.price = price;
this.comission = comission;
this.quantity = quantity;
}
public InvestmentsModel price(float price) {
this.price = price;
return this;
}
public InvestmentsModel comission(float comission) {
this.comission = comission;
return this;
}
public InvestmentsModel quantity(float quantity) {
this.quantity = quantity;
return this;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public float getComission() {
return comission;
}
public void setComission(float comission) {
this.comission = comission;
}
public float getQuantity() {
return quantity;
}
public void setQuantity(float quantity) {
this.quantity = quantity;
}
#Override
public String toString() {
return "[price -> " + this.price + ", comission -> " + this.comission + ", quantity -> " + this.quantity + "]";
}
}
For the response structure, we have:
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
public class GetInvestmentsResponseModel {
#JsonProperty("response")
private List<InvestmentsModel> response;
#JsonProperty("code")
private int code;
public GetInvestmentsResponseModel() {
}
public GetInvestmentsResponseModel(List<InvestmentsModel> response, int code) {
this.response = response;
this.code = code;
}
public GetInvestmentsResponseModel response(List<InvestmentsModel> response) {
this.response = response;
return this;
}
public GetInvestmentsResponseModel code(int code) {
this.code = code;
return this;
}
public List<InvestmentsModel> getResponse() {
return response;
}
public void setResponse(List<InvestmentsModel> response) {
this.response = response;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
And then code becomes:
final String rawResponse = "[{\"response\": [{\"Commission\": 50, \"Price\": 0.5, \"Quantity\": \"20\"}, {\"Commission\": 50, \"Quantity\": 20, \"Price\": 1}, {\"Quantity\": 20, \"Price\": 10, \"Commission\": 50}], \"code\": 200}]";
ObjectMapper mapper = new ObjectMapper();
try {
GetInvestmentsResponseModel[] responseObjects = mapper.readValue(rawResponse, GetInvestmentsResponseModel[].class);
GetInvestmentsResponseModel responseObject = responseObjects[0];
if(responseObject.getCode() == 200) {
List<InvestmentsModel> investmentsModels = responseObject.getResponse();
System.out.println(investmentsModels);
}
} catch (JsonProcessingException e) {
// handle JsonProcessingException
}
Outputs as just as in the InvestmentsModel's toString():
[[price -> 0.5, comission -> 50.0, quantity -> 20.0], [price -> 1.0, comission -> 50.0, quantity -> 20.0], [price -> 10.0, comission -> 50.0, quantity -> 20.0]]
Take one more step further
The final suggestion is to use swagger to both keep track of the api and get rid of the most of the boilerplate code. It can be used both clients and servers, and keeps APIs documented and clean. Please check this out for swagger.
Related
I have this json:
{
"data":[
{
"id": "Character_Alien",
"name": "Trespasser",
"description": "Invader",
"type": {
"value": "outfit",
"displayValue": "Outfit",
"backendValue": "AthenaCharacter"
},
"rarity": {
"value": "uncommon",
"displayValue": "Uncommon"
},
"series": null,
"set": null,
"introduction": {
"chapter": "2022",
"text": "Introduced in 2022",
"backendValue": 22
},
"images": {
"smallIcon": "https://smallimage.png",
"icon": "https://image.png",
"featured": "https://imagebig.png",
"other": null
},
"variants": null,
"searchTags": null,
"metaTags": null
},
{
"id": "Character_Knowing",
"name": "Sinister",
"description": "He holds your fate.",
"type": {
"value": "outfit",
"displayValue": "Outfit",
"backendValue": "AthenaCharacter"
},
"rarity": {
"value": "rare",
"displayValue": "Rare",
"backendValue": "EFortRarity::Rare"
},
"series": null,
"set": {
"value": "Malice",
"text": "Path.",
"backendValue": "GripHate"
},
"introduction": {
"chapter": "2021",
"backendValue": 22
},
"images": {
"smallIcon": "https://smallimage.png",
"icon": "https://image.png",
"featured": "https://imagebig.png",
"other": null
},
"variants": null,
"searchTags": null,
"metaTags": null
}
]
}
It is a JSON 50000+ lines long this is just 2 of the objects of the JSON. I would like to get the "name", the "images" and the "rarity" values only if the "displayValue" is "Outfit". There are a lot of different displayValues so I want to filter the Outfit value first and then I can figure out how to filter the other ones.
I would like to do it in C# but if it can be done easier using Java I can do it there too(I have basic knowledge on both of them)
I have this in mind:
Foreach object in the json
If the object.displayValue = outfit then
string name = object.name
string imagesmall = object.imagesmall
string image = object.image
string imagebig = object.imagebig
String rariry = object.rarity
If it can be done this way, I then want to generate an image for each outfit with the name and rarity in it as text.
Any links to a similar question would be appreciated, It is the 3rd day that I am looking how to do this and this is my last resort.
.Net 6 (no external libraries needed):
using System;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Linq;
string json = "....."; // Removed for brevity
var results = ((JsonArray)(JsonNode.Parse(json))["data"])
.Where(o => (string)(o["type"]["displayValue"]) == "Outfit")
.Select(o => new
{
Name = (string)o["name"],
ImageSmall = (string)o["images"]["smallIcon"],
Image = (string)o["images"]["icon"],
ImageBig = (string)o["images"]["featured"],
Rarity = (string)o["rarity"]["value"]
});
foreach (var x in results) {
Console.WriteLine(x);
}
Output:
{ Name = Trespasser, ImageSmall = https://smallimage.png, Image = https://image.png, ImageBig = https://imagebig.png, Rarity = uncommon }
{ Name = Sinister, ImageSmall = https://smallimage.png, Image = https://image.png, ImageBig = https://imagebig.png, Rarity = rare }
You can be done this using Newtonsoft.Json NuGet easily. I have used the JSON as the string for the example. You can add your source for the relevant.
In case if you have a larger JSON with more attributes, you can use the Past Special option in Visual Studio to create the object Check Here
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
string json = "{" +
"\n\"data\":[\n" +
"{\n\"id\":\"Character_Alien\",\n\"name\": \"Trespasser\",\n\"description\": " +
"\"Invader\",\n\"type\": {\n\"value\": \"outfit\",\n\"displayValue\": \"Outfit\",\n\"backendValue\": " +
"\"AthenaCharacter\"\n},\n\"rarity\": {\n\"value\": \"uncommon\",\n\"displayValue\": \"Uncommon\"\n}" +
",\n\"series\": null,\n\"set\": null,\n\"introduction\": {\n\"chapter\": \"2022\",\n\"text\": \"Introduced in 2022\"," +
"\n\"backendValue\": 22\n}," +
"\n\"images\": {\n\"smallIcon\": \"https://smallimage.png\",\n\"icon\": \"https://image.png\"," +
"\n\"featured\": \"https://imagebig.png\",\n\"other\": null\n},\n\"variants\": null,\n\"searchTags\": null," +
"\n\"metaTags\": null\n},\n{\n\"id\": \"Character_Knowing\",\n\"name\": \"Sinister\"," +
"\n\"description\": \"He holds your fate.\",\n\"type\": {\n\"value\": \"outfit\",\n\"displayValue\": \"Outfit\"," +
"\n\"backendValue\": \"AthenaCharacter\"\n}," +
"\n\"rarity\": {\n\"value\": \"rare\",\n\"displayValue\": \"Rare\",\n\"backendValue\": \"EFortRarity::Rare\"\n}," +
"\n\"series\": null,\n\"set\": {\n\"value\": \"Malice\",\n\"text\": \"Path.\",\n\"backendValue\": \"GripHate\"\n}," +
"\n\"introduction\": {\n\"chapter\": \"2021\",\n\"backendValue\": 22\n},\n\"images\": " +
"{\n\"smallIcon\": \"https://smallimage.png\",\n\"icon\": \"https://image.png\",\n\"featured\": \"https://imagebig.png\"," +
"\n\"other\": null\n},\n\"variants\": null,\n\"searchTags\": null,\n\"metaTags\": null\n}\n]\n" +
"}";
var jsonArr = JsonConvert.DeserializeObject<JsonArr>(json);
var val = jsonArr.Data.Where(w => w.Type.Value == "outfit").Select(s => new Data
{
Name = s.Name,
Rarity = s.Rarity
}).ToList();
Console.WriteLine(json);
Console.ReadKey();
}
}
public class JsonArr
{
[JsonProperty(PropertyName = "data")]
public List<Data> Data { get; set; }
}
public class Data
{
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
[JsonProperty(PropertyName = "type")]
public DataType Type { get; set; }
[JsonProperty(PropertyName = "rarity")]
public Rarity Rarity { get; set; }
}
public class DataType
{
[JsonProperty(PropertyName = "value")]
public string Value { get; set; }
[JsonProperty(PropertyName = "displayValue")]
public string DisplayValue { get; set; }
[JsonProperty(PropertyName = "backendValue")]
public string BackendValue { get; set; }
}
public class Rarity
{
[JsonProperty(PropertyName = "value")]
public string Value { get; set; }
[JsonProperty(PropertyName = "displayValue")]
public string DisplayValue { get; set; }
[JsonProperty(PropertyName = "backendValue")]
public string BackendValue { get; set; }
}
I created an android application to handle network requests using Volley API. I have managed to get a response from the server but I am failing to loop through the different objects of the result JSON and when I add data to a Listview it is only giving me the application's package name with a number added at the end.
This is the response that I want to handle.
{
"list": [
{
"dt": 1637172000,
"main": {
"temp": 301.79,
"feels_like": 300.34,
"temp_min": 298.24,
"temp_max": 301.79,
"pressure": 1008,
"sea_level": 1008,
"grnd_level": 854,
"humidity": 20,
"temp_kf": 3.55
},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01n"
}
],
"clouds": {
"all": 7
},
"wind": {
"speed": 3.77,
"deg": 46,
"gust": 8.98
},
"visibility": 10000,
"pop": 0,
"sys": {
"pod": "n"
},
"dt_txt": "2021-11-17 18:00:00"
}
]
}
The object model and its fields
public class WeatherReportModel {
private int dt;
private JSONObject main;
private JSONArray weather;
private JSONObject clouds;
private JSONObject wind;
private int visibility;
private double pop;
private JSONObject sys;
private String dt_txt;
public WeatherReportModel(
int dt,
JSONObject main,
JSONArray weather,
JSONObject clouds,
JSONObject wind,
int visibility,
double pop,
JSONObject sys,
String dt_txt) {
this.dt = dt;
this.main = main;
this.weather = weather;
this.clouds = clouds;
this.wind = wind;
this.visibility = visibility;
this.pop = pop;
this.sys = sys;
this.dt_txt = dt_txt;
}
}
This is call back function which fetches the responses and add to the Model's object
public void getWeather(VolleyResponseListener forecast) {
List<WeatherReportModel> weatherReportModels = new ArrayList<>();
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray weather_list = response.getJSONArray("list");
// get the first item
for (int i = 0; i < weather_list.length(); i++) {
WeatherReportModel one_day_weather = new WeatherReportModel();
JSONObject first_day_from_api = (JSONObject) weather_list.get(i);
one_day_weather.setDt(first_day_from_api.getInt("dt"));
one_day_weather.setMain(first_day_from_api.getJSONObject("main"));
one_day_weather.setWeather(first_day_from_api.getJSONArray("weather"));
one_day_weather.setClouds(first_day_from_api.getJSONObject("clouds"));
one_day_weather.setWind(first_day_from_api.getJSONObject("wind"));
one_day_weather.setVisibility(first_day_from_api.getInt("visibility"));
one_day_weather.setPop(first_day_from_api.getLong("pop"));
one_day_weather.setSys(first_day_from_api.getJSONObject("sys"));
one_day_weather.setDt_txt(first_day_from_api.getString("dt_txt"));
weatherReportModels.add(one_day_weather);
}
forecast.onResponse(weatherReportModels);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
//get the property call consolidated weather
MySingleton.getInstance(context).addToRequestQueue(request);
}
Usually, ArrayAdapter when used like this will try to use toString() function to get the value and display it. Try to override the toString in the
WeatherReportModel and try again.
I have a Jax-Rs created REST endpoint as defined below:
//It will create the order for the customer who is occupying
//the table identified by the PathParam tableId
#Path("/order/{tableId}")
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON )
public List<ItemOrder> giveOrder(#PathParam("tableId") int tableId, List<ItemOrder> itemOrderList){
Customer currentCustomer = Restaurant.getRestaurant().getCustomerArray().get(tableId);
for (int i = 0; i<itemOrderList.size(); i++){
currentCustomer.giveOrder(itemOrderList.get(i));
}
return itemOrderList;
}
Class ItemOrder has been defined as follows:
#XmlRootElement
public class ItemOrder {
private Item mItem;
private int mNumberOfPlates;
.....
......
.....
}
Class Item has been defined as follows:
#XmlRootElement
public class Item {
private int mItemId;
private String mName;
private float mPrice;
......
......
......
}
Now i am trying to send the JSON Post data from an Android client App as follows:
//Ordering Menu
JSONObject itemOrder1Item = new JSONObject();
JSONObject itemOrder1 = new JSONObject();
try {
itemOrder1Item.put("itemId", 11);
itemOrder1Item.put("itemName","Tea");
itemOrder1Item.put("itemPrice", 10);
itemOrder1.put("Item", itemOrder1Item);
itemOrder1.put("numberOfPlates", 10);
} catch (JSONException e) {
e.printStackTrace();
}
JSONObject itemOrder2Item = new JSONObject();
JSONObject itemOrder2 = new JSONObject();
try {
itemOrder2Item.put("itemId", 22);
itemOrder2Item.put("itemName","Coffee");
itemOrder2Item.put("itemPrice", 20);
itemOrder2.put("Item", itemOrder2Item);
itemOrder2.put("numberOfPlates", 10);
} catch (JSONException e) {
Log.d("Message",e.getMessage());
}
JSONArray jsonArray = new JSONArray();
jsonArray.put(itemOrder1);
jsonArray.put(itemOrder2);
JSONObject itemsOrderListObj = new JSONObject();
try {
itemsOrderListObj.put("itemOrderList", jsonArray);
} catch (JSONException e) {
e.printStackTrace();
}
HTTPAsyncTask asyncTask = new HTTPAsyncTask(getActivity().getApplicationContext(),c, null, itemsOrderListObj, "POST");
asyncTask.execute("http://10.0.2.2:8080/restaurant1/webapi/restaurant/waiters/menus/order/2");
}
But it is throwing some error saying the POST data is not correct. While developing the REST Api i have seen that the server is able to accept data as follows:
[
{
"item": {
"itemId": 11,
"itemName": "Tea",
"itemPrice": 10
},
"numberOfPlates": 5
},
{
"item": {
"itemId": 22,
"itemName": "Coffee",
"itemPrice": 20
},
"numberOfPlates": 5
},
{
"item": {
"itemId": 33,
"itemName": "Bread",
"itemPrice": 30
},
"numberOfPlates": 5
}
]
Now how will i be able to create this JSON Data in my Android app.
Need the help badly.
Used GSON. Its pretty simple as follows;
List<ItemOrder> itemsOrderListObj = new ArrayList<>();
itemsOrderListObj.add(new ItemOrder(new Item(11, "Tea", 10), 10));
itemsOrderListObj.add(new ItemOrder(new Item(22, "Coffee", 20), 10));
itemsOrderListObj.add(new ItemOrder(new Item(33, "Bread", 30), 10));
String itemsOrderListStringJSON = new Gson().toJson(itemsOrderListObj);
Log.i("JSONPOSTDATA", itemsOrderListStringJSON );
HTTPAsyncTask asyncTask = new HTTPAsyncTask(getActivity().getApplicationContext(),c, null, itemsOrderListStringJSON, "POST");
asyncTask.execute("http://10.0.2.2:8080/restaurant1/webapi/restaurant/waiters/menus/order/2");
I have this json file I downloaded online:
{
"price": 1,
"empty": [
0,
0,
0,
0,
0
],
"lowValue": 0,
"highValue": 0
},
and I want to delete everything from
"empty": [
to
],
I've spent a few hours looking at regex stuff and I can't seem to figure out how to make it do what I want it to do.
Edit:
Annamalai Thangaraj's method works until I add more to the file.
{
"price": 1,
"empty": [
0,
0,
0,
0,
0
],
"lowValue": 0,
"highValue": 0
},
{
"price": 500,
"empty": [
5,
0,
3,
6,
9
],
"lowValue": 4,
"highValue": 2
}
which now I'm given an error:
Exception in thread "main" java.lang.ClassCastException: com.google.gson.JsonArray cannot be cast to com.google.gson.JsonObject
My code is exactly:
public static void go() throws IOException {
JsonObject jsonObject = (JsonObject)JsonParser.parse(new FileReader(location));
jsonObject.remove("empty");
JsonArray jsonArray = (JsonArray)JsonParser.parse(new FileReader(location));
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonParser jp = new JsonParser();
JsonElement je = jp.parse(jsonObject.toString());
String prettyJsonString = gson.toJson(je);
FileWriter file = new FileWriter(System.getProperties().getProperty("user.home")+"\\output.json");
try {
file.write(prettyJsonString);
System.out.println("Successfully wrote JSON object to file.");
} catch (IOException e) {
e.printStackTrace();
} finally {
file.flush();
file.close();
}
}
Use the following code to remove element empty from json
JSONObject jsonObject = (JSONObject) jsonParser.parse(new FileReader("File Path"));
jsonObject .remove("empty");
After removing empty element using jsonObject.toJSONString() to get target JSON, Now structure of JSON will be look like this
{
"price": 1,
"lowValue": 0,
"highValue": 0
},
Use a JSON library like Jackson:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
public class JsonDelete {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
String json = "{\"key\":\"value\",\"empty\":[]}";
ObjectNode node = (ObjectNode) mapper.readTree(json);
node.remove("empty");
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(node));
}
}
Outputs:
{
"key" : "value"
}
If you put a '[' at the beginning and a ']' at the end of json file, it becomes a valid json file. Like in your json file, It should be.
[
{
"price": 1,
"empty": [
0,
0,
0,
0,
0
],
"lowValue": 0,
"highValue": 0
},
{
"price": 500,
"empty": [
5,
0,
3,
6,
9
],
"lowValue": 4,
"highValue": 2
}
]
So the final program will be like:--
public class ReadJSONFromFile {
public static void main(String[] args) {
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader("locationOfFIle"));
JSONArray array = (JSONArray) obj;
FileWriter file = new FileWriter("locationOfFIle");
for (int index = 0; index < array.size(); ++index) {
JSONObject jsonObject = (JSONObject) array.get(index);
jsonObject.remove("empty");
file.write(jsonObject.toJSONString());
file.flush();
if (index == array.size() - 1)
file.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
You can also parse your json by ignoring some fields. Look at this example:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
#JsonIgnoreProperties(value = { "empty" })
public class Item {
private long price;
private long lowValue;
private long highValue;
public long getPrice() {
return price;
}
public void setPrice(long price) {
this.price = price;
}
public long getLowValue() {
return lowValue;
}
public void setLowValue(long lowValue) {
this.lowValue = lowValue;
}
public long getHighValue() {
return highValue;
}
public void setHighValue(long highValue) {
this.highValue = highValue;
}
#Override
public String toString() {
return "Item [price=" + price + ", lowValue=" + lowValue + ", highValue=" + highValue + "]";
}
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
String file = "c:\\json";
ObjectMapper mapper = new ObjectMapper();
Item[] items = mapper.readValue(new File(file), Item[].class);
for (Item item : items) {
System.out.println(item);
}
}
}
c:\json contains:
[
{
"price": 1,
"empty": [
0,
0,
0,
0,
0
],
"lowValue": 0,
"highValue": 0
},
{
"price": 2,
"empty": [
0,
0,
0,
0,
0
],
"lowValue": 3,
"highValue": 4
}
]
Output is:
Item [price=1, lowValue=0, highValue=0]
Item [price=2, lowValue=3, highValue=4]
I am getting an array size of zero for the "tweets" array when trying to access the arraylist that it should be stored in. I am using Jackon databinding to a class, which at this point has "worked" as in not gave any errors or exceptions. But, the problem is still that the array is returning empty.
Here is the method where I am accessing the class that the JSON is being binded to:
WeatherDatabaseCreator.java
//Read in files to be parsed.
for (int i = 0; i < twitterFiles.size(); i++) {
File twitterFile = twitterFiles.get(i);
WeatherTweetParser wtp = new WeatherTweetParser(twitterFile);
wtp.mapJavaObject();
tws = new Tweets();
tweets = tws.getTweets();
System.out.print(tweets.size());
tweetIndex = 0;
System.out.println("Parsing and inserting twitter file '" + twitterFile.getAbsolutePath() + "'...");
//Step through all the tweets in each file, using the TweetParser class.
while (true) {
tweet = tweets.get(tweetIndex);
user = tweet.new User();
entity = tweet.new Entities();
userMentions = entity.getUserMentions();
hashtags = entity.getHashtags();
if (tweet.getText() == null) {
break;
}
numParsed++;
Boolean success = wdbm.insertTweet(tweet, user);
if (success == true) {
numInserted++;
}
if (entity.getNumHashtags() > 0){
for (int j = 0; j < entity.getNumHashtags(); j++) {
wdbm.insertHashtag(tweet, hashtags.get(j));
}
}
if (entity.getNumUserMentions() > 0) {
for (int k = 0; k < entity.getNumUserMentions(); k++) {
wdbm.insertReference(tweet, userMentions.get(k));
}
}
if (numParsed % UPDATE_INTERVAL == 0) {
System.out.println(numParsed + " tweets parsed. " + numInserted + " tweets inserted into database...");
}
tweetIndex++;
}
Here is part of the JSON File. The file is made up of an array of tweets, with some nested classes. Here I included two elements of the array:
2014-01-03-11-03.terms.json
{
"tweets": [
{
"filter_level": "medium",
"contributors": null,
"text": "U know your ice fishing at home when ur snacks are sandwiches,chips,dips,beef jerky and all the goodies instead of just a case of beer #mom",
"geo": null,
"retweeted": false,
"in_reply_to_screen_name": null,
"truncated": false,
"lang": "en",
"entities": {
"symbols": [
],
"urls": [
],
"hashtags": [
{
"text": "mom",
"indices": [
135,
139
]
}
],
"user_mentions": [
]
},
"in_reply_to_status_id_str": null,
"id": 419137025376145408,
"source": "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone<\/a>",
"in_reply_to_user_id_str": null,
"favorited": false,
"in_reply_to_status_id": null,
"retweet_count": 0,
"created_at": "Fri Jan 03 16:03:48 +0000 2014",
"in_reply_to_user_id": null,
"favorite_count": 0,
"id_str": "419137025376145408",
"place": null,
"user": {
"location": "",
"default_profile": false,
"profile_background_tile": true,
"statuses_count": 5411,
"lang": "en",
"profile_link_color": "17EBCF",
"profile_banner_url": "https://pbs.twimg.com/profile_banners/408240224/1384838946",
"id": 408240224,
"following": null,
"protected": false,
"favourites_count": 4222,
"profile_text_color": "333333",
"description": "It is what it is, no more, no less. Trust in the Lord. BSU Softball #5. My whole being is happy - Psalm 16:9",
"verified": false,
"contributors_enabled": false,
"profile_sidebar_border_color": "FFFFFF",
"name": "Nicole Anne",
"profile_background_color": "C0DEED",
"created_at": "Wed Nov 09 05:03:58 +0000 2011",
"default_profile_image": false,
"followers_count": 452,
"profile_image_url_https": "https://pbs.twimg.com/profile_images/413270299925164033/mWiJBKP2_normal.jpeg",
"geo_enabled": true,
"profile_background_image_url": "http://a0.twimg.com/profile_background_images/698793822/14d9ce538d96b435ad4449d5385a3ec1.jpeg",
"profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/698793822/14d9ce538d96b435ad4449d5385a3ec1.jpeg",
"follow_request_sent": null,
"url": null,
"utc_offset": -32400,
"time_zone": "Alaska",
"notifications": null,
"profile_use_background_image": true,
"friends_count": 634,
"profile_sidebar_fill_color": "DDEEF6",
"screen_name": "NDupay",
"id_str": "408240224",
"profile_image_url": "http://pbs.twimg.com/profile_images/413270299925164033/mWiJBKP2_normal.jpeg",
"listed_count": 1,
"is_translator": false
},
"coordinates": null
},
{
"filter_level": "medium",
"contributors": null,
"text": "Just watched DeBlasio shovel snow for the cameras and I have to say, his form is terrible. Looks a bit inexperienced.",
"geo": null,
"retweeted": false,
"in_reply_to_screen_name": null,
"truncated": false,
"lang": "en",
"entities": {
"symbols": [
],
"urls": [
],
"hashtags": [
],
"user_mentions": [
]
},
"in_reply_to_status_id_str": null,
"id": 419137026458673152,
"source": "<a href=\"http://twitter.com/download/iphone\" rel=\"nofollow\">Twitter for iPhone<\/a>",
"in_reply_to_user_id_str": null,
"favorited": false,
"in_reply_to_status_id": null,
"retweet_count": 0,
"created_at": "Fri Jan 03 16:03:48 +0000 2014",
"in_reply_to_user_id": null,
"favorite_count": 0,
"id_str": "419137026458673152",
"place": null,
"user": {
"location": "",
"default_profile": false,
"profile_background_tile": false,
"statuses_count": 2609,
"lang": "en",
"profile_link_color": "FF8000",
"id": 163686045,
"following": null,
"protected": false,
"favourites_count": 204,
"profile_text_color": "333333",
"description": "Love learning, Hockey #NYR, music and photography. My family is my whole life.",
"verified": false,
"contributors_enabled": false,
"profile_sidebar_border_color": "EEEEEE",
"name": "Steven Marques",
"profile_background_color": "ACDED6",
"created_at": "Wed Jul 07 01:26:25 +0000 2010",
"default_profile_image": false,
"followers_count": 56,
"profile_image_url_https": "https://pbs.twimg.com/profile_images/378800000795958214/5e3ff928282ad692a36e941e5c5ff628_normal.jpeg",
"geo_enabled": false,
"profile_background_image_url": "http://abs.twimg.com/images/themes/theme18/bg.gif",
"profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme18/bg.gif",
"follow_request_sent": null,
"url": null,
"utc_offset": -18000,
"time_zone": "Eastern Time (US & Canada)",
"notifications": null,
"profile_use_background_image": true,
"friends_count": 58,
"profile_sidebar_fill_color": "F6F6F6",
"screen_name": "SMGafanha",
"id_str": "163686045",
"profile_image_url": "http://pbs.twimg.com/profile_images/378800000795958214/5e3ff928282ad692a36e941e5c5ff628_normal.jpeg",
"listed_count": 2,
"is_translator": false
},
"coordinates": null
},
Here is the Java class that the JSON file is mapped to, followed by the class mapping the JSON to the class:
Tweets.java
public class Tweets {
private ArrayList<Tweet> tweets;
public Tweets() {
tweets = new ArrayList<Tweet>();
}
public ArrayList<Tweet> getTweets() {
return tweets;
}
public void setTweets(ArrayList<Tweet> tweets) {
this.tweets = tweets;
}
public static class Tweet {
private String text;
#JsonProperty("source")
private String postMethod;
#JsonProperty("created_at")
private String time;
#JsonProperty("id")
private String ID;
public Tweet() {
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getID() {
return ID;
}
public void setID(String iD) {
ID = iD;
}
public String getPostMethod() {
return postMethod;
}
public void setPostMethod(String postMethod) {
this.postMethod = postMethod;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public class User {
private String location;
#JsonProperty("screen_name")
private String user;
#JsonProperty("time_zone")
private String timeZone;
#JsonProperty("description")
private String accountDescription;
public User(){
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getTimeZone() {
return timeZone;
}
public void setTimeZone(String timeZone) {
this.timeZone = timeZone;
}
public String getAccountDescription() {
return accountDescription;
}
public void setAccountDescription(String accountDescription) {
this.accountDescription = accountDescription;
}
}
public class Entities {
#JsonProperty("user_mentions")
ArrayList<UserMention> userMentions;
#JsonProperty("hashtags")
ArrayList<Hashtag> hashtags;
public Entities() {
}
public ArrayList<UserMention> getUserMentions() {
return userMentions;
}
public int getNumUserMentions() {
return userMentions.size();
}
public UserMention getUserMention(int index) {
return userMentions.get(index);
}
public void setUserMentions(ArrayList<UserMention> userMentions) {
this.userMentions = userMentions;
}
public ArrayList<Hashtag> getHashtags() {
return hashtags;
}
public int getNumHashtags() {
return hashtags.size();
}
public Hashtag getHashtag(int index) {
return hashtags.get(index);
}
public void setHashtags(ArrayList<Hashtag> hashtags) {
this.hashtags = hashtags;
}
public class UserMention {
#JsonProperty("screen_name")
private String userRef;
public UserMention() {
}
public String getUserRef() {
return userRef;
}
public void setUserRef(String userRef) {
this.userRef = userRef;
}
}
public class Hashtag {
#JsonProperty("text")
private String hashText;
public Hashtag() {
}
public String getHashText() {
return hashText;
}
public void setHashText(String hashText) {
this.hashText = hashText;
}
}
}
}
}
WeatherTweetParser.java
public class WeatherTweetParser {
private static File twitterFile;
public WeatherTweetParser(File twitterFile) {
WeatherTweetParser.twitterFile = twitterFile;
}
public void mapJavaObject() {
String jsonFile = twitterFile.getName();
System.out.println("Mapping JSON to WeatherTweet Class.");
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
mapper.readValue(new File(jsonFile), Tweets.class);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Finished Mapping of JSON File.");
}
And here is the error:
Mapping JSON to WeatherTweet Class.
Finished Mapping of JSON File.
Tweets size: 0
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at database.WeatherDatabaseCreator.main(WeatherDatabaseCreator.java:145)
Parsing and inserting twitter file 'C:\Users\Jared\Documents\Eclipse
WorkSpace\workspace\WeatherDatabaseCreator\2014-01-03-11-03.terms.json'...
On this line of WeatherDatabaseCreator.java:
tweet = tweets.get(tweetIndex);
TL:DR: I understand this error is because the index is out of range, because there is nothing obviously even in the tweets array. But, if the Jackson mapping of the JSON file to my Java Class went through without exceptions, why is the tweets array empty?
while (true) {
tweet = tweets.get(tweetIndex);
user = tweet.new User();
entity = tweet.new Entities();
userMentions = entity.getUserMentions();
hashtags = entity.getHashtags();
if (tweet.getText() == null) {
break;
}
The only break in this loop will work only if getText is null. If getText is not null for all the tweets, you'll get index out of bound exception.
Instead of while(true) you should probably use a check like tweetIndex < tweets.size()
The second problem. You create a Tweets object without loading any items there:
wtp.mapJavaObject();
tws = new Tweets();
tweets = tws.getTweets();
Of course tws object will not have any tweets in this case. What you need to do is to make sure that your mapJavaObjects() method returns a Tweets object with the tweets loaded by ObjectMapper and after this is done your code should look like this:
tweets = wtp.mapJavaObject();
Something like this:
public Tweets mapJavaObject() {
String jsonFile = twitterFile.getName();
Tweets ret = null;
System.out.println("Mapping JSON to WeatherTweet Class.");
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
ret = (Tweets) mapper.readValue(new File(jsonFile), Tweets.class);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Finished Mapping of JSON File.");
retrun ret;
}