I have a Map<String, Object> object, which is obtained from:
new org.yaml.snakeyaml.Yaml().load(someStr)
I want to dump object to a local file, when I use:
new com.fasterxml.jackson.databind.ObjectMapper().writeValue(new File(filePath), object)
I got a proper file, but if some string filed in that object is too long. It broke at multiple lines, and was added line breaks, like this:
SELECT materialid, accountid, device_type, material_type, content
FROM cpc01.material_style_##
What should I do to make ObjectMapper to dump string field into one line instead of multiple lines?
Thanks to #flyx, using SnakeYaml can handle it, my code is as below:
DumperOptions options = new DumperOptions();
options.setSplitLines(false); // remove the line breaks
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); // remove quotes
options.setIndent(2);
options.setPrettyFlow(true); // remove curly brackets
Yaml yaml = new Yaml(options);
// omit some code
yaml.dump(finalYamlMap, new FileWriter(fileName));
Related
I need to write in a specific cell in a .csv file with org.apache.commons.csv library whitout iterate and copy all lines.
I tried this:
Reader reader = Files.newBufferedReader(Paths.get(Properties.dataFilePath));
CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT);
List<CSVRecord> records = csvParser.getRecords();
records.get(rowNumber)[columnIndex] = value;
However it is not allowed.
Edit 1
My IDE mentioned : The type of the expression must be an array type but it resolved to CSVRecord
have you tried it with
value = records.get(rowNumber).get(columnIndex);?
Have a look here, it may help you: https://commons.apache.org/proper/commons-csv/apidocs/org/apache/commons/csv/CSVRecord.html
I am reading two different csv files and populating data into two different objects. I am splitting each line of csv file based on regex(regex is different for two csv files) and populating the object using each data of that array which is obtained by splitting each line using regex as shown below:
public static <T> List<T> readCsv(String filePath, String type) {
List<T> list = new ArrayList<T>();
try {
File file = new File(filePath);
FileInputStream fileInputStream = new FileInputStream(file);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)
list = bufferedReader.lines().skip(1).map(line -> {
T obj = null;
String[] data = null;
if (type.equalsIgnoreCase("Student")) {
data = line.split(",");
ABC abc = new ABC();
abc.setName(data[0]);
abc.setRollNo(data[1]);
abc.setMobileNo(data[2]);
obj = (T)abc;
} else if (type.equalsIgnoreCase("Employee")) {
data = line.split("\\|");
XYZ xyz = new XYZ();s
xyz.setName(Integer.parseInt(data[0]));
xyz.setCity(data[1]);
xyz.setEmployer(data[2]);
xyz.setDesignation(data[3]);
obj = (T)xyz;
}
return obj;
}).collect(Collectors.toList());} catch(Exception e) {
}}
csv files are as below:
i. csv file to populate ABC object:
Name,rollNo,mobileNo
Test1,1000,8888888888
Test2,1001,9999999990
ii. csv file to populate XYZ object
Name|City|Employer|Designation
Test1|City1|Emp1|SSE
Test2|City2|Emp2|
The issue is there can be a missing data for any of the above columns in the csv file as shown in the second csv file. In that case, I will get ArrayIndexOutOfBounds exception.
Can anyone let me know what is the best way to populate the object using the data of the string array?
Thanks in advance.
In addition to the other mistakes you made and that were pointed out to you in the comments your actual problem is caused by line.split("\\|") calling line.split("\\|", 0) which discards the trailing empty String. You need to call it with line.split("\\|", -1) instead and it will work.
The problem appears to be that one or more of the last values on any given CSV line may be empty. In that case, you run into the fact that String.split(String) suppresses trailing empty strings.
Supposing that you can rely on all the fields in fact being present, even if empty, you can simply use the two-arg form of split():
data = line.split(",", -1);
You can find details in that method's API docs.
If you cannot be confident that the fields will be present at all, then you can force them to be by adding delimiters to the end of the input string:
data = (line + ",,").split(",", -1);
Since you only use the first values few values, any extra trailing values introduced by the extra delimiters would be ignored.
I have a JSON file with this structure...
{"id":"1","name":"name","categories":["category1","category2","category3"],"type":"store"}
{"id":"2","name":"name","categories":["category1","category2","category3"],"type":"store"}
which doesn't have a key or commas separating each object. So when I use this code...
File input = new File("test.json");
ObjectMapper mapper = new ObjectMapper();
Map obj = mapper.readValue(input, Map.class);
the obj variable only has the first line in the json file which makes sense as it doesn't know what the key is.
I tried adding one by wrapping the objects like so...
{ "Key": [
{"id":"1","name":"name","categories":["category1","category2","category3"],"type":"store"},
{"id":"2","name":"name","categories":["category1","category2","category3"],"type":"store"}
] }
including adding the commas to separate each as the file did not have any commas to separate them.
While this works...
I have multiple json files that I have to work with
The file sizes are a bit big so it takes a long time to add they "Key" wrap like I did in the example.
I'm hoping to avoid this altogether but not sure if I can. Is there a way to read the json file using the original format into a Map so I can then filter the data as needed?
There is a simple solution that doesn't require file modification. Read your file line by line and then feed a single line to your ObjectMapper. You will get Many instances of Maps that you can store in a List, JsonArray or another map that you will need to create in your code. your code make look like:
ObjectMapper mapper = new ObjectMapper();
List<Map<String, Object> list = new ArrayList<>()
try (
BufferedReader br = new BufferedReader(new FileReader(new File("test.json")))) {
String line;
while((line = br.readLine()) != null) {
Map obj = mapper.readValue(line, Map.class);
list.add(obj)
}
I am using Gson to write to and read from a file.
each time a user is created, I append a line which shows Username and ID.
I do this with the following (UserAccount being my pojo class, br is my buffered reader)::
UserAccount accountObj = new UserAccount();
FileWriter writer = new FileWriter("store.json", true);
accountObj.setUser(NewUserMethod());
accountObj.setID(NewIDMethod());
String json = gson.toJson(accountObj);
writer.write(json);
writer.close();
This makes the json file, which works - like this ::
{"USER":"noob123","ID":"99"}
When a new user does it, It will append the next line like so ::
{"USER":"noob123","ID":99}{"USER":"pro321","ID":100}
When I attempt to read this json file, I got the following error ::
"use JsonReader.setLenient(true) to accept malformed JSON at line 1, column 36"
So I understand it may be incorrect format and may need something like ::
{"ACCOUNT":{"USER":"noob123","ID":99},"ACCOUNT":{"USER":"pro321","ID":100}}
I have spent some time trying to create JSON in this format, or at least reference to the correct USER key when the matching USER name is used. Any help is greatly appreciated.
Thanks
You should use JSONArray to save this information into file. Then you can read content of file into list of UserAccount, add new object into this list.
Then you should override content of file.
E.g. :
UserAccount accountObj = new UserAccount();
accountObj.setUser(NewUserMethod());
accountObj.setID(NewIDMethod());
List<UserAccount> userAccounts = gson.fromJson(<jsonContent>, new TypeToken<List<UserAccount>>() {
}.getType());
userAccounts.add(accountObj);
String json = gson.toJson(userAccounts);
writer.write(json);
writer.close();
The JSON example file consists of:
{
"1st_key": "value1",
"2nd_key": "value2",
"object_keys": {
"obj_1st": "value1",
"obj_2nd": "value2",
"obj_3rd": "value3",
}
}
I read the JSON file into a String with this StringBuilder method, in order to add the newlines into the string itself. So the String looks exactly like the JSON file above.
public String getJsonContent(String fileName) {
StringBuilder result = new StringBuilder("");
File file = new File(fileName);
try (Scanner scanner = new Scanner(file)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
result.append(line).append("\n");
}
scanner.close();
} catch (IOException e) {
e.printStackTrace();
}
return result.toString();
}
Then I translate the JSON file into an Object using MongoDB API (with DBObject, BasicDBObject and util.JSON) and I call out the Object section I need to change, which is 'object_keys':
File jsonFile = new File(C:\\example.json);
String jsonString = getJsonContent(jsonFile.getAbsolutePath());
DBObject jsonObject = (DBObject)JSON.parse(jsonString);
BasicDBObject objectKeys = (BasicDBObject) jsonObject.get("object_keys");
Now I can write new values into the Object using the PUT method like this:
objectKeys.put("obj_1st","NEW_VALUE1");
objectKeys.put("obj_2nd","NEW_VALUE2");
objectKeys.put("obj_3rd","NEW_VALUE3");
! This following part not needed, check out my answer below.
After I have changed the object, I need to write it back into the json file, so I need to translate the Object into a String. There are two methods to do this, either one works.
String newJSON = jsonObject.toString();
or
String newJSON = JSON.serialize(jsonObject);
Then I write the content back into the file using PrintWriter
PrintWriter writer = new PrintWriter(C:\\example.json)
writer.print(newJSON);
writer.close();
The problem I am facing now is that the String that is written is in a single line with no formatting whatosever. Somewhere along the way it lost all the newlines. So it basically looks like this:
{"1st_key": "value1","2nd_key": "value2","object_keys": { "obj_1st": "NEW_VALUE1","obj_2nd": "NEW_VALUE2","obj_3rd": "NEW_VALUE3", }}
I need to write the JSON file back in the same format as shown in the beginning, keeping all the tabulation, spaces etc.
Is this possible somehow ?
When you want something formatted the way you said it is addressed as writing to a file in a pretty/beautiful way. For example: Output beautiful json. A quick search on google found what i believe to solve your problem.
Solution
You're going to have to use a json parser of some sort. I personally prefer org.json and would recommend it if you are manipulating the json data, but you may also like json-io which is really good for json serialization with no external dependencies.
With json-io, it's as simple as
String formattedJson = JsonWriter.formatJson(jsonObject.toString())
With org.json, you simply pass an int to the toString method.
Thanks Saraiva, I found a surprisingly simple solution by Googling around with the words 'pretty printing JSON' and used the Google GSON library. I downloaded the .jar and added it to my project in Eclipse.
These are the new imports I needed:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
Since I already had the JSON Object (jsonObject) readily available from my previous code, I only needed to add two new lines:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String newJSON = gson.toJson(jsonObject);
Now when I use writer.print(newJSON); it will write the JSON in the right format, beautifully formatted and indented.