I am writing a program that generates PDF files of printable exams. I have all the exam questions stored in a JSON file. The catch is that the exam is in Czech, so there are many special characters (specifically ěščřžýáíé). When I run the program in Idea, it works perfectly - the output is exactly as it is supposed to be.
But when I build the jar executable, the generated files have chunks of wrong encoded text. Specifically anything that went through the JSON parser. Everything hard coded like headers etc. is encoded properly, so the mistake must be in the parser.
The JSON input file is encoded in UTF-8.
I use these two methods to parse the JSON file.
private static Category[] parseJSON(){
JSONParser jsonParser = new JSONParser();
Category[] categories = new Category[0];
try (FileReader reader = new FileReader("otazky.json")){
// Read JSON file
Object obj = jsonParser.parse(reader);
JSONArray categoryJSONList = (JSONArray) obj;
java.util.List<JSONObject> categoryList = new ArrayList<>(categoryJSONList);
categories = new Category[categoryJSONList.size()];
int i = 0;
for (JSONObject category : categoryList) {
categories[i] = parseCategoryObject(category);
i++;
}
} catch (ParseException | IOException e) {
e.printStackTrace();
}
return categories;
}
private static Category parseCategoryObject(JSONObject category) {
String categoryName = (String) category.get("name");
int generateCount = (int) (long) category.get("generateCount");
JSONArray questionsJSONArray = (JSONArray) category.get("questions");
java.util.List<JSONObject> questionJSONList = new ArrayList<>(questionsJSONArray);
Question[] questions = new Question[questionJSONList.size()];
int j = 0;
for (JSONObject question : questionJSONList) {
JSONArray answers = (JSONArray) question.get("answers");
String s = (String) question.get("question");
String[] a = new String[answers.size()];
for (int i = 0; i < answers.size(); i++) {
a[i] = answers.get(i).toString();
}
int c = (int) (long) question.get("correct");
Question q = new Question(s, a, c);
questions[j] = q;
j++;
}
return new Category(categoryName, questions, generateCount);
}
The output looks like this:
...
Právnà norma:
a) je obecnÄ› závaznĂ© pravidlo chovánĂ, kterĂ© nemusĂ mĂt urÄŤitou formu,
b) nemĹŻĹľe bĂ˝t součástĂ právnĂho pĹ™edpisu,
...
While I would need it to look like this:
...
Právní norma:
a) je obecně závazné pravidlo chování, které nemusí mít určitou formu,
b) nemůže být součástí právního předpisu,
...
Benjamin Urquhart suggested that I try using InputStringReader and FileInputStream instead of FileReader to read the file, because with FileReader you cannot specify the encoding (system default is used). I find those two methods hard to use, but I found an alternative - Files.readAllLines, which is fairly easy to use, and it worked.
Related
I am trying to loop through a JSON file and append the value each time to patientList. So far I believe I have done the hard part, however the simplest part seems to be taking a lot of time, that is appending the values to patientList. My getJsonFile method gets the path of the JSON file. The format of the JSON file is below. I am able to print jsonArray so I know I am good up to that point, but lost after that.
Json file.
[{"patient":1},{"patient":2},{"patient":3},{"patient":4},{"patient":5},{"patient":6},{"patient":7},{"patient":8},{"patient":9}]
getJsonFile method.
private List<Integer> getJsonFile(String path)
{
List<Integer> patientList = new ArrayList<>();
try (FileReader reader = new FileReader(path))
{
JSONParser jsonParser = new JSONParser();
JSONArray jsonArray = (JSONArray)jsonParser.parse(reader);
System.out.println(jsonArray);
// Update patientList
for (int i = 0; i < jsonArray.size(); i++ )
{
patientList.add(jsonArray(i));
}
}
catch(IOException | ParseException | NullPointerException e)
{
e.printStackTrace();
}
return patientList;
}
Your JSONArray contains objects: {"patient":1}
So you could not add patientList.add(jsonArray(i));
You have to access the int value inside that object:
JSONObject patient = jsonArray.getJsonObject(i);
patientList.add(patient.getInt("patient");
Edit
Well. You are using the simple-json library with quite limit feature and outdated. In this case you have to cast the data yourself:
JSONObject patient = (JSONObject)jsonArray.get(i);
patientList.add((Integer)patient.get("patient");
I recommend you remove this lib and use existing JSON feature of Java. If you want more advance feature, Jackson/GSon is the library to use.
I'm trying to generate a json file from my data but I end up generating only one json object before I get this exception Java Cannot generate more than one JSON text
This is my code:
OutputStream fos = new FileOutputStream("new_fake_students.json",false);
JsonGenerator g = Json.createGenerator(fos);
while (matcher.find())
{
String temp = matcher.group();
String[] values = temp.split(",");
if(values.length>=4)
{
g.writeStartObject();
g.write("id",values[0]);
g.write("name",values[1]+values[2]);
g.write("major",values[3]);
g.writeEnd();
}
}
g.close();
fos.close();
}
As it seems that you generate more than one object, are you sure you don't want to generate an array of objects? Perhaps:
OutputStream fos = new FileOutputStream("new_fake_students.json",false);
JsonGenerator g = Json.createGenerator(fos);
g.writeStartArray(); // start the array
while (matcher.find())
{
String temp = matcher.group();
String[] values = temp.split(",");
if(values.length>=4)
{
g.writeStartObject();
g.write("id",values[0]);
g.write("name",values[1]+values[2]);
g.write("major",values[3]);
g.writeEndObject(); // does g.writeEnd() even exists?
}
}
g.writeEndArray(); // close that array
This question already has answers here:
What’s the best way to load a JSONObject from a json text file?
(9 answers)
Closed 9 years ago.
What would be the easiest way to load a file containing JSON into a JSONObject.
parsing a file into a JSONObject - w/o the intermittent String object (arguably memory wasting)
This is what I have, but it throws an exception:
public class AlphabetGestures {
private Map<Character,Vector<Point>> mMap;
public AlphabetGestures(String jsonFileName) throws JSONException {
mMap = new HashMap<Character,Vector<Point>>() ;
// parsing a file into a JSONObject - w/o the intermittent String object (arguably memory wasting)
File f = new File(jsonFileName); // making File object for .json file.
JSONObject masterJSON = new JSONObject(f.toString());
// giving .json file string to jsonvalue parser
JSONArray characters = masterJSON.names();
for ( int c = 0; c < characters.length(); c++ ) {
// this loop will get each object from jsonArr
String character = characters.getString(c);
JSONArray pointsJSON = masterJSON.getJSONArray(character);
// this will get each element from jsonarray and make subarray for (A, B C ... )
Vector<Point> pointsVector = new Vector<Point>();
for ( int i = 0; i < pointsJSON.length(); i++ ) {
JSONArray point = pointsJSON.getJSONArray(i);
pointsVector.add(new Point(point.getInt(0), point.getInt(1)));
}
mMap.put(character.charAt(0), pointsVector);
// put pointVector in mMap with key temp.
}
}
public void scribble(char letter, UiDevice uiDevice){
//System.out.println("here");
//AlphabetGestures Y = new AlphabetGestures() ;
Vector<Point> points = mMap.get(letter) ;
System.out.println("------------------");
System.out.println(points);
if(points!=null){
uiDevice.swipe(points.toArray(new Point[points.size()]), 5);
}
}
Output:- while running the test case
Error in testAccordion:
java.lang.NoSuchMethodError: ionmini.automate.AlphabetGestures.<init>
at ionmini.automate.AccordionDrag.testAccordion(AccordionDrag.java:33)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.android.uiautomator.testrunner.UiAutomatorTestRunner.start(UiAutomatorTestRunner.java:160)
at com.android.uiautomator.testrunner.UiAutomatorTestRunner.run(UiAutomatorTestRunner.java:96)
at com.android.commands.uiautomator.RunTestCommand.run(RunTestCommand.java:91)
at com.android.commands.uiautomator.Launcher.main(Launcher.java:83)
at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:235)
at dalvik.system.NativeStart.main(Native Method)
ObjectMapper can easily solve your problem
ObjectMapper mapper = new ObjectMapper();
File from = new File("path to file");
JsonNode masterJSON = mapper.readTree(from);
you need to handle IOException as needed.
I need to parse list of json stored in a single file !
What I have done so far is,
test.json file contains:
{"location":"lille","lat":28.4,"long":51.7,"country":"FR"}
with this file I have the code below
public class JsonReader {
public static void main(String[] args) throws ParseException {
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader("c:\\test.json"));
JSONObject locationjson= (JSONObject) obj;
String location= (String) locationjson.get("location");
System.out.printf("%s",location);
long lat = (Long) locationjson.get("lat");
System.out.printf("\t%d",lat);
//similarly for other objects
This is a working code and I am able to print only one json in the file test.json
Now if I have to print a list of json in file: test1.json as shown below: each line is a single valid json and there are list of json in a single file. What I need is to parse each json and print it in each line. Will using a bean class work?
{"Atlas":{"location":"lille","lat":28.4,"long":51.7,"country":"FR"}}
{"Atlas":{"location":"luxum","lat":24.1,"long":54.7,"country":"LU"}}
{"Atlas":{"location":"ghent","lat":28.1,"long":50.1,"country":"BE"}}
{"Atlas":{"location":"alborg","lat":23.4,"long":53.7,"country":"DN"}}
Your help is appreciated !
The JSON should have a root node.
If you don't have that, you can read from the file line-by-line, and pass each line into the JSONParser wrapped in a StringReader (since the JSONParser.parse() method takes a Reader).
e.g.
BufferedReader in
= new BufferedReader(new FileReader("test.json"));
while(!done) {
String s = in.readLine();
if (s == null) {
done = true;
}
else {
StringReader sr = new StringReader(s);
// etc...
}
}
Edit: I've assumed you're using JSONParser. If you're using a different parser (which one?) then it may take a String argument.
JSONParser.parse() also takes the String as an aurgument.
Read the file with FileReader and for each line that you read use JSONParser.parse(String) method.
First of all:make sure you have created a class just for the son item for each row that has the string properties in the header file and synthesized in the implementation file.Then create a property array in the implementation file that will be doing the parsing.In the parse file..use NSJSONSerialization in your retrieve data method:
-(void)retrieveData{
NSURL * url =[NSURL URLWithString:getDataURL];
NSData *data =[NSData dataWithContentsOfURL:url];
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
newsArray = [[NSMutableArray alloc]init];
for (int i = 0; i < json.count; i++){
{
NSString * cID =[[json objectAtIndex:i]objectForKey:#"Name1"];
NSString * cName = [[json objectAtIndex:i]objectForKey:#"name2"];
NSString * cState =[[json objectAtIndex:i]objectForKey:#"name3"];
NSString * cPopulation =[[json objectAtIndex:i]objectForKey:#"Edition"];
NSString * cCountry =[[json objectAtIndex:i]objectForKey:#"name4"];
City *myCity = [[City alloc]initWithCityID:cID andCityName:cName andCityState:cState andCityPopulation:cPopulation andCityCountry:cCountry];
[newsArray addObject:myCity];
}
[self.myTableView reloadData];
}
}
Then retrieve the son objects or arrays and enter them in the name 1 name 2 section to parse them to your table.Also make sure you have already setup your Table and assigned it a cell identifier and indexed to row.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//static NSString *strIdentifier=#"identity";
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
// cell.textLabel.text = [NSString stringWithFormat:#"Cell %d",indexPath.row];
City *currentCity =[newsArray objectAtIndex:indexPath.row];
cell.textLabel.text = currentCity.Name1;
cell.detailTextLabel.text = currentCity.Name2;
return cell;
}
I've been trying to work out how to obtain the travel time between two locations (walking, driving etc...).
As I understand it, the only way to do this accurately is by retrieving a KML file from google, then parsing it.
Research has shown that it then needs to be parsed with SAX. The problem is, I can't seem to work out how to extract the correct variables (the time). Does anybody know if / how this can be done?
Many thanks for your help,
Pete.
Parsing XML (what KML basically is), using a SAX-Parser: http://www.dreamincode.net/forums/blog/324/entry-2683-parsing-xml-in-java-part-1-sax/
<kml>
<Document>
<Placemark>
<name>Route</name>
<description>Distance: 1.4 mi (about 30 mins)<br/>Map data ©2011 Tele Atlas </description>
</Placemark>
</Document>
</kml>
In the example you can see, that the guessed time is stored in the "description"-Tag. It's saved in the last "Placemark"-Tag in the KML-File and it has a "<name>Route</name>"-Tag.
Getting this Tag with the SAX-Parser and extracting the time using regex should be easy done.
Here's my JSOUP implementation for getting tracks
public ArrayList<ArrayList<LatLng>> getAllTracks() {
ArrayList<ArrayList<LatLng>> allTracks = new ArrayList<ArrayList<LatLng>>();
try {
StringBuilder buf = new StringBuilder();
InputStream json = MyApplication.getInstance().getAssets().open("track.kml");
BufferedReader in = new BufferedReader(new InputStreamReader(json));
String str;
while ((str = in.readLine()) != null) {
buf.append(str);
}
in.close();
String html = buf.toString();
Document doc = Jsoup.parse(html, "", Parser.xmlParser());
ArrayList<String> tracksString = new ArrayList<String>();
for (Element e : doc.select("coordinates")) {
tracksString.add(e.toString().replace("<coordinates>", "").replace("</coordinates>", ""));
}
for (int i = 0; i < tracksString.size(); i++) {
ArrayList<LatLng> oneTrack = new ArrayList<LatLng>();
ArrayList<String> oneTrackString = new ArrayList<String>(Arrays.asList(tracksString.get(i).split("\\s+")));
for (int k = 1; k < oneTrackString.size(); k++) {
LatLng latLng = new LatLng(Double.parseDouble(oneTrackString.get(k).split(",")[0]), Double.parseDouble(oneTrackString.get(k)
.split(",")[1]));
oneTrack.add(latLng);
}
allTracks.add(oneTrack);
}
} catch (Exception e) {
e.printStackTrace();
}
return allTracks;
}