Trying to learn about Jackson some, so I'm writing a simple program that reads a file/creates one to store some JSON in it. From the Jackson website I figured out how to read and write from the file, but in the case of my rudimentary program, i'd like to append as well. I'm basically trying to store a list of shopping lists. There is a shopping list object which has store name, amd items for that store.
The trouble is that I cannot figure a way to append another entry to the end of the file (in JSON format). Here is what I am working with so far, you can ignore the first bit it's just a silly console scanner asking for input:
public class JacksonExample {
static ObjectMapper mapper = new ObjectMapper();
static File file = new File("C:/Users/stephen.protzman/Desktop/user.json");
static List<ShoppingList> master = new ArrayList<ShoppingList>();
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
boolean running = true;
while (running) {
System.out.println("[ 1 ] Add a new shopping list");
System.out.println("[ 2 ] View all shopping lists");
System.out.println("[ 3 ] Save all shopping lists");
int choice = Integer.parseInt(in.nextLine());
switch (choice) {
case 1:
getNewList();
case 2:
display();
case 3:
running = false;
}
}
in.close();
}
public static void getNewList() {
boolean more = true;
String store, temp;
List<String> items = new ArrayList<String>();
Scanner s = new Scanner(System.in);
System.out.println("Enter the store: ");
store = s.nextLine();
System.out.println("Enter each item [If done type 'DONE'] :");
while (more) {
temp = s.nextLine();
if (temp != null) {
if (temp.toUpperCase().equals("DONE")) {
more = false;
} else {
items.add(temp);
}
}
}
save(store, items);
s.close();
}
public static void display() {
try {
ShoppingList list = mapper.readValue(file, ShoppingList.class);
System.out.println(mapper.defaultPrettyPrintingWriter()
.writeValueAsString(list));
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void save(String store, List<String> items) {
//load in old one
try {
ShoppingList list = mapper.readValue(file, ShoppingList.class);
System.out.println(mapper.defaultPrettyPrintingWriter()
.writeValueAsString(list));
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//add to end of older list
ShoppingList tempList = new ShoppingList();
tempList.setStore(store);
tempList.setItems(items);
master.add(tempList);
try {
mapper.writeValue(file, master);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I want to keep using ObjectMapper (considering im trying to learn Jackson) I just havent found a way to append yet is all. Any ideas?
To append content, you need to use Streaming API to create JsonGenerator; and then you can give this generator to ObjectMapper to write to. So something like:
JsonGenerator g = mapper.getFactory().createGenerator(outputStream);
mapper.writeValue(g, valueToWrite);
// and more
g.close();
Below method can be used to write objects into a json file in append mode. it first reads your existing json file and adds new java objects to JSON file.
public static void appendWriteToJson() {
ObjectMapper mapper = new ObjectMapper();
try {
// Object to JSON in file
JsonDaoImpl js = new JsonDaoImpl();
URL resourceUrl = js.getClass().getResource("/data/actionbean.json");
System.out.println(resourceUrl);
File file = new File(resourceUrl.toURI());
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file, true))); // append mode file writer
mapper.writeValue(out, DummyBeanObject);
} catch (Exception e) {
e.printStackTrace();
}
}
Related
I have a binary file having some list where each list has group of similar objects
I am using ObjectInputStream to read the list series one by one
Now, instead of directly printing the list I want to iterate through the list and print the elements separately.
Following is my code -
class ReadObject54 {
public static void readObject(String filename) {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
Object obj = null;
boolean cond = true;
while(cond) {
try {
obj = ois.readObject();
} catch (EOFException e) {
break;
}
if(obj == null) {
cond = false;
} else {
System.out.println(obj);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here the obj is reading series of list from a binary file.
Each list has similar objects
But different list have different objects
Here I am using System.out.println(obj) to directly print the list
But instead I want to iterate through the list and print the elements separately
How to do so?
I have two classes (writeArray and readArray) which should write an array of {10, 20, 30} and print it in a demo class but it only prints out 10, with no 20 or 30, and I don't understand if it isn't reading the whole array or if there's an issue with my demo code.
Here's the array class:
import java.io.*;
public class FileArray{
public static void writeArray(){
String fileName = "file.bin";
int[] array = {10, 20, 30};
try{
FileOutputStream fileOs = new FileOutputStream(fileName);
DataOutputStream os = new DataOutputStream(fileOs);
for (int i = 0; i < 3; i++)
os.writeInt(array[i]);
os.close();
fileOs.close();
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void readArray(){
String fileName = "file.bin";
int[] array1;
try{
FileInputStream fileIs = new FileInputStream(fileName);
DataInputStream is = new DataInputStream(fileIs);
System.out.println(is.readInt());
is.close();
fileIs.close();
}
catch (FileNotFoundException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here is the display class:
public class FileArrayDemo {
public static void main(String[] args){
FileArray write = new FileArray();
write.writeArray();
System.out.println("Done writing. Now reading.");
FileArray read = new FileArray();
read.readArray();
}
}
You're only reading a single int. Instead, you should loop until you reach EOF:
while (true) {
try {
System.out.println(is.readInt());
} catch (EOFException e) {
// Reached the end of the file, break out the loop
break;
}
}
just add the for loop you used in your write method with your
System.out.println(is.readInt());
my code has to read in two different Object Types (Bestellung, AKunde) through a ObjectOutputStream and save it in a csv file, which works.
But when i try to read them from the file it doesn't work.
Here is the code:
OutputStream:
LinkedList<Bestellung> bestellListe = verwaltungBestell.getBestellListe();
try {
fileOutputStream = new FileOutputStream(file);
outputStream = new ObjectOutputStream(fileOutputStream);
for (AKunde kunde : kundenliste) {
outputStream.writeObject(kunde);
}
for (Bestellung bestellung : bestellListe) {
outputStream.writeObject(bestellung);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
InputStream:
ArrayList<AKunde> kundenImport = new ArrayList<AKunde>();
ArrayList<Bestellung> bestellungenImport = new ArrayList<Bestellung>();
boolean cont = true;
try {
ObjectInputStream objectStream = new ObjectInputStream(new FileInputStream(directorie));
while (cont) {
AKunde kunde = null;
try {
kunde = (AKunde) objectStream.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (kunde != null) {
kundenImport.add(kunde);
} else {
cont = false;
}
}
while (cont) {
Bestellung bestellung = null;
try {
bestellung = (Bestellung) objectStream.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (bestellung != null) {
bestellungenImport.add(bestellung);
} else {
cont = false;
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
}
But it won't read the "Bestellungen" and won't save them into "bestellungenImport".
Anyone has a solution???
Your code never reaches the Bestellung reader part.
You have a false assumption that kunde =(AKunde)objectStream.readObject(); returns null.
Instead, it throws exception.
Oneway you can do is cast it like #luk2302.
Another way is to add a object count when writing your object stream:
outputStream.writeInt(kundenliste.size());
for (AKunde kunde : kundenliste) {
outputStream.writeObject(kunde);
}
outputStream.writeInt(bestellListe.size());
for (Bestellung bestellung : bestellListe) {
outputStream.writeObject(bestellung);
}
Then replace your while(cont) loop with a for each loop:
int kundeCount = objectStream.readInt();
for (int i = 0; i < kundeCount; i++) {
// Read and import kunde
}
You need to change your logic for reading objects. There are two main issues:
you never reset cont so the second while loop will never do anything
even if you did that you would always skip the first Bestellung since it was already read when the second loop is reached
I would propose something along the lines of:
Object object = objectStream.readObject();
if (object instanceof AKunde) {
kundenImport.add((AKunde) object);
} else if (object instanceof Bestellung) {
bestellungenImport.add((Bestellung) object);
} else {
// something else was read
}
You simply need to loop over this code and add proper error handling where needed.
I would suggest, you change the way you write your objects to ObjectOutputStream in the first place:
Directly write the kundenListe and bestellListe objects, so you dont't have to worry about types or number of elements when reading the objects again. Your stream of object then always contains two objects, the two lists.
// use try-with-resources if you're on Java 7 or newer
try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file))) {
// write the complete list of objects
outputStream.writeObject(kundenliste);
outputStream.writeObject(bestellListe);
} catch (IOException e) {
e.printStackTrace(); //TODO proper exception handling
}
Then you could read it just like that:
ArrayList<AKunde> kundenImport = new ArrayList<>();
ArrayList<Bestellung> bestellungenImport = new ArrayList<>();
//again try-with-resources
try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file))) {
kundenImport.addAll((List) inputStream.readObject());
bestellungenImport.addAll((List) inputStream.readObject());
} catch (IOException | ClassNotFoundException e) { //multi-catch, if Java 7 or newer
e.printStackTrace(); //TODO proper exception handling
}
Further reads:
The try-with-resources Statement
Catching Multiple Exception Types (...)
How to invoke Array-name from IPSUM.java class to updateArticleView method by passing its name simply?
eg. in highlighted row, i want to achieve this article.setText(Ipsum.LateralPull[0]); dynamically
updateArticleView method
IPSUM.java
A very simple way to do that is to use a HashMap<String, String[]> and you can put each array to the map with its current field name as its key:
map.put("LateralPull", new String[]{"LateralPaull"});
So you can simply call:
map.get(name);
But If you don't want to use HashMap for any reason you can use java reflection. Here is a sample code:
public class Main {
public static void main(String[] args) {
try {
Test test = new Test();
Field field = Test.class.getDeclaredField("list");
String[] list = (String[]) field.get(test);
System.out.println(list[0]);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HashMap<String, String[]> map = new HashMap<>();
map.put("hasahn", new String[]{"df"});
}
private static class Test{
String[] list = new String[]{"Item 1"};
}
}
The output is: Item 1.
I want to retrieve the results of a method in a single string each time the function is called. I have a method which returns different results every time. I want to put all the results as a single string.
Tried to use append() method of java but the results are getting replaced every time as the function is called each time. but i need to retrieve the previous results as well.
my code is as follows.
public void createPanel2()
{
panel2 = new JPanel();
panel2.setLayout( new FlowLayout() );
query = new JLabel("query");
textbox =new JTextField(10);
submit = new JButton("submit");
panel2.add(query);
panel2.add(textbox);
panel2.add(submit);
submit.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
String str =textbox.getText();
String serverUrl = "http://localhost:8983/solr/collection1";
SolrServer solr = new HttpSolrServer(serverUrl);
try {
for (SolrDocument next : simpleSolrQuery(solr, str +
"")) {
prettyPrint(System.out, next);
}
} catch (SolrServerException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
initFilterAndButton();
}
SolrDocumentList simpleSolrQuery(SolrServer solr,
String query) throws SolrServerException {
SolrQuery solrQuery = new SolrQuery(query);
//SolrQuery query = new SolrQuery(searchTerm);
//query.setStart((pageNum - 1) * numItemsPerPage);
//query.setRows(numItemsPerPage);
//solrQuery.setRows(Integer.MAX_VALUE);
QueryResponse resp = solr.query(solrQuery);
//System.out.println("resp"+resp);
final SolrDocumentList hits = resp.getResults();
/*for (SolrDocument d : hits) {
for (Iterator<Map.Entry<String, Object>> i = d.iterator(); i
.hasNext();) {
Map.Entry<String, Object> e2 = i.next();
System.out.println(e2.getKey() + "\t" + e2.getValue());
}
System.out.println("------------------------");
}*/
System.out.println("hits"+resp.getElapsedTime());
System.out.println("size"+hits.size());
System.out.println("num found"+hits.getNumFound());
//String str ="hello";
//createPanel1(hits);
return hits;
}
void prettyPrint(PrintStream out, SolrDocument doc) {
List<String> sortedFieldNames =
new ArrayList<String>(doc.getFieldNames());
Collections.sort(sortedFieldNames);
out.println();
// StringBuilder contentstring=new StringBuilder();
// ArrayList<String> contents=new ArrayList<>();
for (String field : sortedFieldNames) {
if(field.equals("content")){
textarea.append(String.format("%s: %s",
field,doc.getFieldValue(field)+"\n"));
out.println(String.format("\t%s: %s",
field, doc.getFieldValue(field)));
contentsmethod(doc.getFieldValue(field).toString());
// contents.add(doc.getFieldValue(field).toString());
// System.out.println("conetnts"+contentstring);
}
}
// String test=contentstring.toString();
out.println();
}
public void contentsmethod(String fieldsvalues) {
// TODO Auto-generated method stub
StringBuilder contentstring=new StringBuilder();
contentstring.append(fieldsvalues);
try {
Desktop.getDesktop().browse(new URL(serverQuery+URLEncoder.encode(contentstring.toString())).toURI());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
The code above is calling the prettyPrint method every time and the results of that method should be retrieved to a single string which should hold the previous called results as well.
here i want to retrieve the results of contentstring.append(fieldsvalues);
But contentstring is returning only the current results and not appending the previous results.
this is obvious because the method is called everytime. Is there any work around to retrieve the previous results along with the current ones as well.
You need to move this StringBuilder contentstring=new StringBuilder(); outside of your method. Every time your method call is made, you create a new String. This is why you only get the current value.
You can make a List outside of your method and add the resulting String in that list. Otherwhise, you can create the string outside and append the results to it without instantiating a new one at every method call.
You have to do something like this:
StringBuilder contentstring = new StringBuilder();
public void contentsmethod(String fieldsvalues) {
// TODO Auto-generated method stub
contentstring.append(fieldsvalues);
try {
Desktop.getDesktop().browse(new URL(serverQuery+URLEncoder.encode(contentstring.toString())).toURI());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}