Updating Json file when String ist not present in list - java

I am coding a Discord Giveaway Bot with Java. I am saving all the details of the Giveaway to a JSON file. Now I want to read the entries list and if the Users ID is not in the list I want to add it and save the file.
Here is the Giveaway Class:
public class Giveaway {
private String prize;
private long time;
private Integer winners;
private List<String> entries;
public Giveaway(String prize, Integer winners, long time, List<String> entries) {
this.prize = prize;
this.winners = winners;
this.time = time;
this.entries = entries;
}
public Giveaway() {}
public String getPrize() {
return prize;
}
public void setPrize(String prize) {
this.prize = prize;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public Integer getWinners() {
return winners;
}
public void setWinners(Integer winners) {
this.winners = winners;
}
public List<String> getEntries() {
return entries;
}
public void setEntries(List<String> entries) {
this.entries = entries;
}
}
When the GW is created the JSON looks like this:
{
"prize": "Discord Nitro",
"time": 1641732935,
"winners": 2,
"entries": []
}
Then when the user clicks a button it should read the list look if the ID is in the list and if not add the id. But when I save the list the whole JSON file changes.
How I read it out and save it:
public class ButtonClick extends ListenerAdapter {
private static Reader reader;
private static Giveaway giveaway = new Giveaway();
public void onButtonClick(ButtonClickEvent event) {
event.deferEdit().queue();
try {
reader = Files.newBufferedReader(Path.of(GiveawayStats.getGiveawayStats().getAbsolutePath()));
} catch (IOException e) {
e.printStackTrace();
}
if (event.getButton().getId().equals("gwEnter")) {
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(reader).getAsJsonObject();
JsonArray jsonEntries = obj.get("entries").getAsJsonArray();
long time = obj.get("time").getAsLong();
List<String> entries = new ArrayList<>();
for (JsonElement entrie : jsonEntries) {
entries.add(entrie.toString());
}
if (entries.contains(event.getMember().getId())) {
event.getChannel().sendMessage("Already in!").queue();
} else {
entries.add(event.getUser().getId().strip());
printToJson(entries);
}
}
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void printToJson(List<String> entries) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setVersion(2.0);
Gson gson = gsonBuilder.setPrettyPrinting().create();
giveaway.setEntries(entries);
try (Writer writer = new FileWriter(GiveawayStats.getGiveawayStats().getPath())) {
gson.toJson(giveaway, writer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
After the print so JSON the file looks like this:
{
"time": 0,
"entries": [
"695629580014321747"
]
}
And when I click the Button again it looks like this:
{
"time": 0,
"entries": [
"\"695629580014321747\"",
"695629580014321747"
]
}
So why is my IF condition not working?

You are using entrie.toString() which gives you the string that is used for console output. You should be using entrie.getAsString() instead.
Furthermore, you are also using a lot of deprecated things with JsonParser which should be replaced. new JsonParser().parse(...) should be replaced by JsonParser.parseReader(...).
Above all that, it is highly recommended using a database for this kind of task. Something such as SQLite or Redis would be much better at handling concurrent changes and redundancy. Or at least, you should use a try-with-resources for your reader.
try (Reader reader = ...) {
JsonElement json = JsonParser.parseReader(reader).getAsJsonObject();
...
}

Related

Fetching timings info from json using Retrofit

I have some problem fetching info from JSON. I'm confused about whether to use ArrayList or any other data type to retrieve data from JSON server.
I've tried to fetch data using
ArrayList<String>
in model.
Below is data format of JSON
[
{
"sun_timing": "{\"sun_from\":\"12:30\",\"sun_to\":\"4:30\"}",
"mon_timing": "{\"mon_from\":\"3:00\",\"mon_to\":\"4:30\"}"
},
{
"sun_timing": "{\"sun_from\":\"12:30\",\"sun_to\":\"4:30\"}",
"mon_timing": "{\"mon_from\":\"3:00\",\"mon_to\":\"4:30\"}"
}
]
I want to fetch all sun_timing data and mon_timing data.
That is sun_from,sun_to and mon_from,mon_to data.
Your Plain Old Java Object(POJO) for your json looks like this:
public class Example {
#SerializedName("sun_timing")
#Expose
private String sunTiming;
#SerializedName("mon_timing")
#Expose
private String monTiming;
public String getSunTiming() {
return sunTiming;
}
public void setSunTiming(String sunTiming) {
this.sunTiming = sunTiming;
}
public String getMonTiming() {
return monTiming;
}
public void setMonTiming(String monTiming) {
this.monTiming = monTiming;
}
}
See also: https://stackoverflow.com/a/40973753/10452701 for more details about How to get json via Rerofit2.
try this out working for me
private List<String> getSunList() {
ArrayList sunList = new ArrayList<String>()
String sun_json = your_json_string
try {
JSONObject jsonObject = new JSONObject(sun_json)
Log.d(TAG, "jsonObject: "+jsonObject)
Log.d(TAG, "jsonObject: "+sun_json)
JSONArray jsonArray = jsonObject.getJSONArray("sun_timing")
for (i in 0 until jsonArray.length())
{
JSONObject obj = jsonArray.get(i) as JSONObject
String sun_from = obj.getString("sun_from")
String sun_to = obj.getString("sun_to")
sunList.add(sun_from)
Log.d(TAG, "obj= "+obj)
}
}
catch (e: java.lang.Exception)
{
}
return sunList
}

Change my writeJsonFile function from GSON to Jackson

I have some code that takes in a list of descriptors and writes them to different JSON files using the GSON library. I am now trying to change that library to Jackson. I am not a Jackson expert so I'm looking for some help. Here is my code when I am using GSON:
Descriptor Class:
public class Descriptor {
#SerializedName("BatchName")
private String batchName;
#SerializedName("Metadata")
private Metadata metadata;
#SerializedName("SampleInfo")
private SampleInfoJsonModel sampleInfo;
#SerializedName("Files")
private List<String> files;
#SerializedName("ClientData")
private ClientData clientData;
#SerializedName("CaseName")
private String caseName;
public Descriptor() {
this.metadata = new Metadata();
this.sampleInfo = new SampleInfoJsonModel();
this.files = new ArrayList<String>();
this.clientData = new ClientData();
}
public String getBatchName() {
return batchName;
}
public void setBatchName(String batchName) {
this.batchName = batchName;
}
public Metadata getMetadata() {
return metadata;
}
public void setMetadata(Metadata metadata) {
this.metadata = metadata;
}
public SampleInfoJsonModel getSampleInfo() {
return sampleInfo;
}
public void setSampleInfo(SampleInfoJsonModel sampleInfo) {
this.sampleInfo = sampleInfo;
}
public List<String> getFiles() {
return files;
}
public void setFiles(List<String> files) {
this.files = files;
}
public ClientData getClientData() {
return clientData;
}
public void setClientData(ClientData clientData) {
this.clientData = clientData;
}
public String getCaseName() {
return caseName;
}
public void setCaseName(String caseName) {
this.caseName = caseName;
}
public ClientData getClientDataNoCountryCodes() {
// TODO Auto-generated method stub
return null ;
}
}
My write JSON File function:
public static void writeJsonFile(List<Descriptor> descriptors) {
try {
for(Descriptor descriptor : descriptors) {
BufferedWriter buffWrite = new BufferedWriter(new FileWriter("descriptor_"+descriptor.getCaseName()+".json"));
Gson gson = new GsonBuilder().setPrettyPrinting().create();
buffWrite.write(gson.toJson(descriptor));
buffWrite.close();
}
}
catch (IOException ioe) {
System.err.println("Error while writing to json file in writeJsonFile: ");
ioe.printStackTrace();
}
}
Here is what I have written in Jackson:
BufferedWriter buffWrite = new BufferedWriter(new FileWriter("descriptor_"+descriptor.getCaseName()+".json"));
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
buffWrite.write(mapper.writeValueAsString(descriptor));
Is this the equivalent of the code below in GSON?
BufferedWriter buffWrite = new BufferedWriter(new FileWriter("descriptor_"+descriptor.getCaseName()+".json"));
Gson gson = new GsonBuilder().setPrettyPrinting().create();
buffWrite.write(gson.toJson(descriptor));
buffWrite.close();
I think you are looking for generating a pretty JSON output for your Object and trying to write it into a file.
You have to make sure that you are using #SerializedName equivalent annotation from jackson which is #JsonProperty on your object properties.
Also you can use following to prettify JSON using jackson ObjectMapper
mapper.writerWithDefaultPrettyPrinter().writeValueAsString( descriptorObj )
NOTE that setting SerializationFeature.INDENT_OUTPUT will also help doing the same as you are already thinking.
Also Files APIs are really useful for file related operations.
I hope this will help!

Best approach of reading data from text file and adding it to arraylist in android

I am working on a project to get into android development, having some knowledge of java before I am thinking of reading data from a text file, which will be formatted like this;
Type: House
Image link: www.bit.ly/image1
Name: Black
Download Link: www.bit.ly/image1download
----------
Type: Car
Image link: www.bit.ly/image2
Name: yellow
Download Link: www.bit.ly/image2download
----------
Type: Backyard
Image link: www.bit.ly/image3
Name: Green
Download Link: www.bit.ly/image3download
----------
Type: Window
Image link: www.bit.ly/image4
Name: Solid
Download Link: www.bit.ly/image4download
----------
Type: Table
Image link: www.bit.ly/image5
Name: Brown
Download Link: www.bit.ly/image5download
----------
The data contains 4 pieces of information per set, Type, Image, Name and Download. I need a way of reading this and saving/writing it to a arraylist which I then can display in a listview that I will have on my app. (I am currently looking at tutorials on creating listview, if you know any useful tutorials please let me know)
Arraylist <String> data = new ArrayList<String>();
Data.add(“House”,” www.bit.ly/image1”,”black”,”www.bit.ly/image1download”);
Data.add(“Car”,” www.bit.ly/image2”,”yellow”,” www.bit.ly/image2download”);
……..
……..
In reality there will be a lot more data then just 5 sets , so I want to use for loop to loop through each data data and add it to the data arraylist.
I am not sure how I can approach this, any help is welcomed, I am really stuck. Please let me know if I have not explained my question properly.
EDITED:
Would this be the correct way of reading data from a textfile?
Scanner content = new Scanner(new File("Data.txt"));
ArrayList<String> data = new ArrayList<String>();
while (content.hasNext()){
data.add(content.next());
}
content.close();
Or is this another way in android
Before start go through this link for reading
How can I read a text file in Android?
Use PoJo Models for your needs,
Create a PoJo class like this
public class Film {
private String filmName;
private String mainStar;
public String getFilmName() {
return filmName;
}
public void setFilmName(String filmName) {
this.filmName = filmName;
}
public String getMainStar() {
return mainStar;
}
public void setMainStar(String mainStar) {
this.mainStar = mainStar;
}
}
Create ArrayList
private ArrayList<Film > filmArray=new ArrayList<Film>();
Store Each arraylist with instance of your PoJo class like this
for(int i=0;i<sizei++)
{
Film film=new Film();
film.setFilmName("your value");
film.setMainStar("your value");
filmArray.add(film);
}
and then access list of values in arraylist of PoJo class in filmArray list.
Simple and elegant solution.
Here is the parser
public class FileParser {
private static final String DATA_TERMINATION = "----------";
private static final String TYPE="Type";
private static final String IMAGE="Image link";
private static final String NAME= "Name";
private static final String DWNLD_LNK= "Download Link";
public static void main(String[] args) {
FileParser parser = new FileParser();
try {
for(Data d:parser.parseDataFile(new File("F:\\data.txt"))){
System.out.println(TYPE+":"+d.getType());
System.out.println(IMAGE+":"+d.getImage());
System.out.println(NAME+":"+d.getName());
System.out.println(DWNLD_LNK+":"+d.getLink());
System.out.println(DATA_TERMINATION);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public List<Data> parseDataFile(File input) throws Exception{
List<Data> output =null;
List<String> fileOp= null;
try {
validateInput(input);
fileOp = readFile(input);
output = parseData(fileOp);
} catch (Exception e) {
throw e;
}
return output;
}
private List<Data> parseData(List<String> fileOp) {
List<Data> output =null;
output = new ArrayList<Data>();
Data data;
data = new Data();
for(String line:fileOp){
if(DATA_TERMINATION.equalsIgnoreCase(line)){
output.add(data);
data = new Data();
}else{
parseField(data,line);
}
}
return output;
}
private void parseField(Data data, String line) {
StringTokenizer tokenzr = new StringTokenizer(line,":");
if(tokenzr.countTokens() !=2){
System.out.println("Cant parse line"+line);
}else{
switch (tokenzr.nextToken()) {
case TYPE:
data.setType(tokenzr.nextToken());
break;
case IMAGE:
data.setImage(tokenzr.nextToken());
break;
case NAME:
data.setName(tokenzr.nextToken());
break;
case DWNLD_LNK:
data.setLink(tokenzr.nextToken());
break;
default:
break;
}
}
}
private List<String> readFile(File input) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(input)));
String line = null;
List<String> op = new ArrayList<String>();
try {
while((line = reader.readLine()) != null){
op.add(line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw e;
}
return op;
}
private void validateInput(File input) throws Exception {
if(input == null){
throw new Exception("Null input");
}else if(!input.exists() || !input.isFile() || !input.canRead() ) {
throw new Exception("File not readable");
}
}
}
Do this way define a setter getter class to hold and return values like this :
Data.class
public class Data {
String type,Image,Name,Link ;
public Data() {
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getImage() {
return Image;
}
public void setImage(String image) {
Image = image;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getLink() {
return Link;
}
public void setLink(String link) {
Link = link;
}
}
using for loop set data in a arraylist
Arraylist <Data> arrayListData = new ArrayList<Data>();
for(int i=0;i<arrayListData .size();i++){
Data data=new Data();
data.setType("");
...
...
...
arrayListData.add(data);
}
and to fetch data from arraylist
String type= arrayListData.get(position).getType();
Updated :
read .txt file like this , I am assuming your text file is saved in sdcard of device :
public void readfile() {
StringBuilder text = new StringBuilder();
File sdcard = Environment.getExternalStorageDirectory();
ArrayList<Data> arrayList=new ArrayList<Data>();
//Get the text file
File file = new File(sdcard,"textfile.txt");
//Read text from file
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
Data data=new Data();
while ((line = br.readLine()) != null) {
text.append(line);
text.append('\n');
if(line.contains(":")){
int index=line.indexOf(":");
String s=line.substring(index+1).trim();
if(line.contains("Type")){
data.setType(s);
}
if(line.contains("Image")){
data.setImage(s);
}
if(line.contains("Name")){
data.setName(s);
}
if(line.contains("Download")){
data.setLink(s);
}
}
if(line.contains("-")){
arrayList.add(data);
data=new Data();
}
}
System.out.println(text);
br.close();
}
catch (IOException e) {
e.printStackTrace();
}
}

How to get value of jsonObject value in android?

I am building an android application and I am new to json. I am fetching below josn formate -
{
"contact"[
{
"key1": "hey1",
"key2": [
{
"key3": "hey2"
}
]
}
]
}
I am using below code to fetch key1 value. Now problem I am facing is how to fetch key3 value -
jsonString = http.makeServiceCall(url, ServiceHandler.GET, null);
if (jsonString != null) {
try {
JSONObject jsonObj = new JSONObject(jsonString);
// Getting JSON Array node
questions = jsonObj.getJSONArray(TAG_CONTACTS);
for (int i = 0; i < questions.length(); i++) {
temp_obj = questions.getJSONObject(i);
key1Array.add(temp_obj.getString("key1").toString());
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Please help me
If you want to use Gson to parse your json data. Let try it:
First of all, you must modify your json like this:
{
"contact":[
{
"key1": "hey1",
"key2": [
{
"key3": "hey2"
}
]
}
]
}
Second add Gson to your libs and sync build.gradle: download here extract it, and copy/past gson-2.2.4.gson to libs folder.
Third Create some class:
FullContents.java:
public class FullContents {
private List<ObjectKey> contact;
public List<ObjectKey> getContact() {
return contact;
}
public void setContact(List<ObjectKey> contact) {
this.contact = contact;
}
}
ObjectKey.java:
public class ObjectKey {
private String key1;
private List<ObjectKey3> key2;
public List<ObjectKey3> getKey2() {
return key2;
}
public void setKey2(List<ObjectKey3> key2) {
this.key2 = key2;
}
public String getKey1(){
return key1;
}
public void setKey1(String key1){
this.key1 = key1;
}
}
ObjectKey3.java:
public class ObjectKey3 {
private String key3;
public String getKey3(){
return key3;
}
public void setKey3(String key3){
this.key3 = key3;
}
}
And Finally, get data from url:
private class ParseByGson extends AsyncTask<String,Void,FullContents> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected FullContents doInBackground(String... params) {
FullContents fullContents = null;
try {
URL url=new URL(params[0]);
InputStreamReader reader=new InputStreamReader(url.openStream(),"UTF-8");
fullContents=new Gson().fromJson(reader,FullContents.class);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return fullContents;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(FullContents results) {
super.onPostExecute(results);
ObjectKey objectKey = results.getContact().get(0);
Log.e(">>",objectKey.getKey1()+"--");
}
}
you can put below code to onCreate:
ParseByGson parseByGson = new ParseByGson();
parseByGson.execute(urlStringHere);
Update: Explain
1st of all: your json appears to be not valid (missing ':' after "content");
After reviewing thins:
You can use the named getters to retrieve many types of results (object, int, string, etc);
JSONObject contact = jsonObj.getJSONObject("contact"); // {"key1":"hey1","key2":[{"key3":"hey2"}]}
or
String key1 = jsonObj.getString("key1"); // hey1
To retrieve key3, you should use:
JSONObject contact = jsonObj.getJSONObject("contact");
JSONObject key2 = contact.getJSONObject("key2");
String key3 = key2.getString("key3");
Adapt the following code to what you are coding
for (int i = 0; i < questions.length(); i++) {
temp_obj = questions.getJSONObject(i);
key1Array.add(temp_obj.getString("key1"));
JSONObject temp_objKey2 = temp_obj.getJSONObject("key2");
Key2Object key2Object = new Key2Object();
key2Object.add(temp_objKey2.getString("key3"));
key1Array.add(key2Object);
}

Load very heavy stream with GSON

I'm trying to read a very heavy JSON (over than 6000 objects) and store them on a hash map to insert it into my database later.
But the problem is that I face with OOM and that's cause from my heavy JSON, however GSON library should rid me from this situation, but it is not !!!
Any ideas?
public Map<String,String> readJsonStream(InputStream in) throws IOException
{
JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
Map<String,String> contentMap = new HashMap<String,String>();
Gson mGson = new Gson();
contentMap = mGson.fromJson(reader, contentMap.getClass());
reader.close();
return contentMap;
}
From my experience, yes you can use google GSON to stream JSON data this is an example how to do it :
APIModel result = new APIModel();
try {
HttpResponse response;
HttpClient myClient = new DefaultHttpClient();
HttpPost myConnection = new HttpPost(APIParam.API_001_PRESENT(
serial_id, api_key));
try {
response = myClient.execute(myConnection);
Reader streamReader = new InputStreamReader(response
.getEntity().getContent());
JsonReader reader = new JsonReader(streamReader);
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
if (name.equals("result")) {
if (reader.nextString() == "NG") {
result.setResult(Util.API_001_RESULT_NG);
break;
}
} else if (name.equals("items")) {
result = readItemsArray(reader);
} else {
reader.skipValue(); // avoid some unhandle events
}
}
reader.endObject();
reader.close();
} catch (Exception e) {
e.printStackTrace();
result.setResult(Util.API_001_RESULT_NG);
}
} catch (Exception e) {
e.printStackTrace();
result.setResult(Util.API_001_RESULT_NG);
}
readItemsArray function :
// read items array
private APIModel readItemsArray(JsonReader reader) throws IOException {
APIModel result = new APIModel();
String item_name, file_name, data;
result.setResult(Util.API_001_RESULT_OK);
reader.beginArray();
while (reader.hasNext()) {
item_name = "";
file_name = "";
data = "";
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
if (name.equals("name")) {
item_name = reader.nextString();
} else if (name.equals("file")) {
file_name = reader.nextString();
} else if (name.equals("data")) {
data = reader.nextString();
} else {
reader.skipValue();
}
}
reader.endObject();
result.populateModel("null", item_name, file_name, data);
}
reader.endArray();
return result;
}
API Model Class :
public class APIModel {
private int result;
private String error_title;
private String error_message;
private ArrayList<String> type;
private ArrayList<String> item_name;
private ArrayList<String> file_name;
private ArrayList<String> data;
public APIModel() {
result = -1;
error_title = "";
error_message = "";
setType(new ArrayList<String>());
setItem_name(new ArrayList<String>());
setFile_name(new ArrayList<String>());
setData(new ArrayList<String>());
}
public void populateModel(String type, String item_name, String file_name, String data) {
this.type.add(type);
this.item_name.add(item_name);
this.file_name.add(file_name);
this.data.add(data);
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public String getError_title() {
return error_title;
}
public void setError_title(String error_title) {
this.error_title = error_title;
}
public String getError_message() {
return error_message;
}
public void setError_message(String error_message) {
this.error_message = error_message;
}
public ArrayList<String> getType() {
return type;
}
public void setType(ArrayList<String> type) {
this.type = type;
}
public ArrayList<String> getItem_name() {
return item_name;
}
public void setItem_name(ArrayList<String> item_name) {
this.item_name = item_name;
}
public ArrayList<String> getFile_name() {
return file_name;
}
public void setFile_name(ArrayList<String> file_name) {
this.file_name = file_name;
}
public ArrayList<String> getData() {
return data;
}
public void setData(ArrayList<String> data) {
this.data = data;
}
}
before I use the streaming API from google GSON I also got OOM error because the JSON data I got is very big data (many images and sounds in Base64 encoding) but with GSON streaming I can overcome that error because it reads the data per token not all at once. And for Jackson JSON library I think it also have streaming API and how to use it almost same with my implementation with google GSON. I hope my answer can help you and if you have another question about my answer feel free to ask in the comment :)

Categories

Resources