JSON to Export .txt Order in Java - java

I have this code, and the string is coming from JSON from the server, and I use these if statements to prioritize what I want to get exported to the text file, but when I run it, the output isnt the output I am expecting, see below:
JSONObject attributeObject = objects.getJSONObject(objectAttribute);
String[] elementList = JSONObject.getNames(attributeObject);
for (String attributeName : elementList) {
if (attribute.equals("Custodian")){
String value = objects.getString("attributeValue");
System.out.print(value+",");
out.write(value);
out.append(",");
}
if (attribute.equals("Custodian Delegate")){
String value = objects.getString("attributeValue");
System.out.print(value+",");
out.write(value);
out.append(",");
}
if (attribute.equals("Authentication Directory")){
String value = objects.getString("attributeValue");
System.out.print(value+",");
out.write(value);
out.append(",");
}
if (attribute.equals("User ID")){
String value = objects.getString("attributeValue");
System.out.println(value);
out.write(value);
out.append(",");
out.newLine();
}
}
Expected output based from the if statements:
JDoe,CPer,Active Directory, No
But once I run it, the output becomes:
Active Directory,JDoe,CPer,No
Is there an easier way to fix this? My only problem is that the Authentication Directory goes first when I start running the program. Any tips? I would greatly appreciate.
Thanks in advance

make your life easy by creating a Model class
class Model{
String JDoe=""; //this is an example, so change attribute names using naming convention
String CPer="";
String Active_Directory="";
String No="";
#Override
public String toString(){
return JDoe+", " +CPer+", " +Active_Directory+", " + No;
}
}
now change your code to use this model, and only update the class Model without writing anything to the file.
for example:
Model model = new Model();
...
for(whatever condition is){ //start of the loop
if (attribute.equals("Custodian")){
String value = objects.getString("attributeValue");
model.CPer=value;
//System.out.print(value+",");
//out.write(value); <-- skip this
//out.append(","); <-- skip this
}
...
}
//after the loop
out.write(model.toString());
NOTE:
if you have two loops place Model model = new Model();
inside your outter loop

The output might be correct. You are iterating over all keys of the JSON-object. The resulting order does not depend on the order of your if-satements. In every loop only a single if-condition matches. The given snippet will output the elements in the same order as in the returned array.
The .getNames() returnes the array of the field names of the given Object. Then you are iterating over theses field names. Therfore the attribute value will have the same value per cycle. It is impossible that two if-condition will match because attribute can not equal for example "Custodian" and "Custodian Delegate" at thes same time.
It seems like the array contains the attributes in an alphabetic order. Therefore the attributeName-variable is "Authentication Directory" during the first cycle.

Related

How to detect a string within an ArrayList with a for each loop?

public String searchNumber(String name){
String result = "";
for(Person search: person){
if(search.getName().contains(name)){
result += search.getNumber();
}
else{
result = " number not known ";
}
}
return result;
}
Looking for some advice here on how to fix this problem I am having. This is a method which I expect to use my getName method to see if the local instance (name) is within the ArrayList. However, I am only getting the latter result to display only, saying "number not known." My step-by-step process goes like this: I create an instance of Person (search), access the getName method, access the contains method since it is originally a String method, and then check to see if the local instance is within the arrayList. If my logic is incorrect, please correct me. Also, does accessing the person array prevent me from using a String type in my for-each loop, since it is a Person object? I tried do this with a String type, but could not continue further since I could not convert to a String within the for-each loop.
Here's a breakdown of your current code:
You consider every object in the person list. If that person's name matches the parameter, you get the number from it. Otherwise, you set result to the error message. Note that the otherwise clause is applied for EACH person, instead of at the end if NOBODY was found to have the same name. That is, even if you find the right person and assign result to their number, if the next person isn't correct then you overwrite result to the error message again.
To make sure the error message is only assigned once and only if NOBODY is found, you need to check whether that is true after going through everyone (since you can't know if nobody is found before checking everyone!). The trick now is to find some clause which is always true when nobody was found. But that can just be if result was never modified. That is, you can set result to the default value at declaration, then only modify it to a number if the right person was found. Also, I am assuming that only one person should be found and you don't want to actually concatenate the numbers together (which is what you are doing by using +=). That said, try this:
public String searchNumber(String name){
for (Person search: person){
if (search.getName().contains(name)){
return search.getNumber();
}
}
return " number not known ";
}
Basically you can just return after finding your record
String notFound = " number not known ";
for(Person search: person){
if(search.getName().contains(name)){
return search.getNumber();
}
}
return notFound;
String result = null;
for(Person search: person){
if(search.getName().contains(name)){
result += search.getNumber();
}
}
if(result == null){
result = "number not known ";
}
return result;
Since there is no way to tell the last element in for-in loop, so the alternative is basing on result == null

Cannot add new object to a set, values come from a file

I am trying to create a public instance method that takes no arguments and returns no values. It is required to get an input from a user to select a file, this part I have no issues with. The method needs to make use of the BufferReader and Scanner Objects. So that it can read the file selected. For each line that is read, a new object should be created and its instance variables set using the values found in the file.
That object that is created should then be added to a list. This is where I am having issues, it won't let me add the new object to the list. Below is my code:
public void readInEntrants()
{
String pathname = OUFileChooser.getFilename();
File aFile = new File(pathname);
Scanner bufferedScanner = null;
Set<Entrant> entrantSet = new HashSet<>();
try
{
String currentEntrantLine;
Scanner lineScanner;
bufferedScanner = new Scanner(new BufferedReader(new FileReader(aFile)));
while (bufferedScanner.hasNextLine())
{
currentEntrantLine = bufferedScanner.nextLine();
lineScanner = new Scanner(currentEntrantLine);
lineScanner.useDelimiter(" ");
currentEntrantLine = lineScanner.next();
entrantSet.add(new Entrant(currentEntrantLine)); // <----- Here is where I am having trouble. It won't let me add the new object to the class Entrant
}
}
catch (Exception anException)
{
System.out.println("Error: " + anException);
}
finally
{
try
{
bufferedScanner.close();
}
catch (Exception anException)
{
System.out.println("Error: " + anException);
}
}
return entrantSet;
}
I'm not sure what to do. Could anyone see what I am doing wrong?
Sorry for got to add that it is a compilation issue, it will not compile properly.
Use an IDE ,I bet you dont (otherwise it would mark compilation error immediatly with red -> you use return in void method ) and in this case you would see other errors.
(off: this would go to comment section however under 50reputation I am not allowed to do that. Stackoverflow should change this imo. )
First of all:
You marked function readInEntrants as public void so you can't use return inside.
You could either remove return entrantSet; instruction or change function definition to public Set<Entrant> readInEntrants.
Concerning problem you have:
Basing on comment you left on beatrice answer I think you have only parameterless constructor for 'Entrant' class, while you try to create it passing string as parameter.
new Entrant(currentEntrantLine)
What you need to do is define Entrant class constructor that accept String as it's argument. For example:
public Entrant(String dataToParse)
{
// here you parse data from string to entrant fields
}
On the side:
You use bufferedReader to read entire file line at once and that's ok, but then you define Scanner lineScanner to iterate through line elements and then use it only once.
This way for file... let's say:
One Two Three
Four Five Six
Your while loop would work like this:
Store "One Two Three" inside currentEntrantLine.
Create scanner that'll work on "One Two Three", and set it to use space as delimiter.
Use .next to "Finds and returns the next complete token" (see documentation) and then store value inside currentEntrantLine. This way contents of currentEntrantLine is "One". Not entire line.
In next iteration you would have scanner working on "Four Five Six" and "Four" as currentEntranceLine content.
It seems the constructor of entrant class does not have any argument. Pass String as an argument type in the constructor to set the String field inside the Entrant class .

Xtend: filter an ArrayList of Strings

I have an array list declared like this:
val aName = new ArrayList
I add names in this array via the add().
When I print them, I only want to print specific names (e.g. all with names "Charlie" and working at the department Finance).
In my for loop, I have this:
for (m: aName.filter[!CDirectoryFacade::instance.isNameUsed(toString)])
{
print(m)
}
The loop above did not print the name at all.
Because my function isNameUsed() did not receive the string as I expect, but rather it receives the address as a String
org.generator.myDsl.myDslGenerator#67bd0a26
However, I do not seem to have problem when I do not use filter().
for (m: aName)
{
if (!CDirectoryFacade::instance.isNameUsed(m))
{
print(m)
}
}
Can anyone suggest on how to use the filter() with Strings?
It's hard to tell because your code snippet doesn't provide any types and it is not clear where name comes from in the print expression.
But the code above should probably read like this:
for (m: aName.filter[!CDirectoryFacade::instance.isNameUsed(toString)])
{
print(m.name) // instead of print(name)
}
I could be even more concise:
aName.filter[!CDirectoryFacade::instance.isNameUsed(toString)].forEach[ print(name) ]

What to return when printing out Objects using the toString method and a for each loop?

I currently have a toString method, similar to the one below. Please ignore that the Objects are only temporarily named. I have done this so that there is no confusion between the types of each variable etc.:
#Override
public String toString() {
for(Object object : ArrayList) {
System.out.println("This object is a " + object.getVariableA() + " and a " + object.getVariableB() + ".");
}
return null;
}
However the toString method requires me to return a value. I would obviously just want to return the Strings that I'm printing, although if I place a return statement there, it will only print one Object and not all of the ones I am looping through. What would be the best way to print all these values and not simply return null as I don't want this printing out after all the Objects? I also want to ensure that each of these Objects are printed on separate lines like they currently are so please don't suggest solutions that include one long joined String without line breaks as this is not suitable in this situation.
Thanks in advance!
toString shouldn't output anything at all. Its job is to return an appropriate string representation of the relevant object, not to output that representation anywhere. That's outside its problem domain.
Instead, build and return a string (probably by using a StringBuilder).
E.g., something like:
#Override
public String toString() {
StringBuilder sb = new StringBuilder(some_appropriate_size);
for(Object object : ArrayList) {
sb.append("This object is a ")
.append(object.getVariableA())
.append(" and a ")
.append(object.getVariableB())
.append(".\n");
}
return sb.toString();
}
I also want to ensure that each of these Objects are printed on separate lines like they currently are so please don't suggest solutions that include one long joined String as this is not suitable in this situation.
The above puts the items from the array list on separate "lines" (via the \n). But "one long joined String" is the only appropriate thing for toString to do. If you want a different result, you must use a different method, rather than breaking the contract of toString.
You could create a String and add what you want each iteration:
#Override
public String toString() {
String result = "";
for(Object object : ArrayList) {
result += "This object is a " + object.getVariableA() + " and a " + object.getVariableB() + ".\n");
}
return result;
}
Don't forget to add the "\n" new-line character, so you print each "partial result" in one different line.
You state in your question that:
I also want to ensure that each of these Objects are printed on separate lines like they currently are so please don't suggest solutions that include one long joined String as this is not suitable in this situation.
Then you probably shouldn't be using toString(); that's not what's it's for. It is for returning a single string that is some representation of the object. It should never be outputting anything.
Add a getter to your class that returns the List of objects, output them as you would like. If you really wanted to make the class self-printing, add a print(OutputStream os) method that takes the supplied OutputStream (or maybe a PrintStream instead) and will do so.

Loading a CSV file and creating new class Instances from the values

I have a class defined like this, with the appropriate getter and setter methods...
public class Album {
private int id;
private String artist;
private String name;
private int published;
}
I also have a .csv file that stores this content for a number of Albums. In the file, one line represents one Album.
I'm trying to read the information from the .csv file, and then use the setters of the Album class to assign the values. Here is my code...
public Map<Integer, Album> load() {
Scanner scanner = new Scanner(fileName);
Map<Integer, Album> loadedAlbums = new HashMap<Integer, Album>();
while(scanner.hasNextLine()) {
Album album = new Album();
String[] albumDivided = scanner.nextLine().split(",");
//in the .csv file every unit of information is divided by a comma.
album.setId(Integer.parseInt(albumDivided[0])); //this is line 11.
album.setArtist(albumDivided[1]);
album.setName(albumDivided[2]);
album.setPublished(Integer.parseInt(albumDivided[3]));
loadedAlbums.put(album.getId(), album);
}
return loadedAlbums;
}
However, trying to use this code, I get the following Exception:
java.lang.NumberFormatException: For input string: "albums.csv" at line 11.
Could you please help me to understand the cause of this problem.
Well the problem is described to you by the Exception...
A NumberFormatException would have been triggered by one of your Integer.parseInt() lines. The line of your code that is triggering the exception is Line 11 (as per the exception message) - not sure which one this is but its probably the first Integer.parseInt() line.
Your code is trying to convert the value "albums.csv" to a number, which is obviously isn't. So somewhere in your CSV file you must have a line that contains the value albums.csv where it is expecting a number.
Hope this helps pinpoint the problem.
Since you don't want the whole solution here is a hint to resolve your problem:
You should take a look at the API documentation of the Scanner class. Take a really close look on the constructor that expects a single String parameter (as you use it in your code).
As far as I can tell, albumDivided[0] will containt "1." which will not be able to parse to an integer because of the dot. Either remove the dot from your csv file, or create a new string that removes the dot before you parse it to Integer. The approach might look something like this:
String newString;
for(int i=0;i<albumDivided[0].length-1;i++){ //length -1 to remove the dot
newString = newString + albumDivided[0].charAt(i); //get the string stored in albumDivided[0] and add each char to the new string
}

Categories