0

I want to create a website/API, that reads in a csv and returns the wanted resoureces. I use SpringBoot: the Spring Web dependency. For reading in the csv I import implementation('com.opencsv:opencsv:5.6') to dependencies in my build.gradle-file. I decided to use the following structure:

Four java-files in src\main\java\com\example\so:

The bean Car.java:

package com.example.so;

import com.opencsv.bean.CsvBindByName;

import java.math.BigDecimal;

public class Car {

    @CsvBindByName
    private int id;
    @CsvBindByName(column = "name")
    private String brand;
    @CsvBindByName
    private BigDecimal price;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "id=" + id +
                ", brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}

To display the correct car I use CarController.java:

package com.example.so;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CarController {

    @GetMapping("/car/{id}")
    public Car findcar(@PathVariable int id) {
        for (Car car: ReadInCSV.cars){
            if (car.getId()==id){
                System.out.println(car.toString());
                return car;
            }
        }
        return null;
    }

    @GetMapping("")
    public String findcar() {
        return "Hi!";
    }
}

To read in the csv-file ReadInCSV.java:

package com.example.so;

import com.opencsv.bean.CsvToBeanBuilder;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.List;

public class ReadInCSV {
    static final String fileName="src/main/resources/static/abc.csv";
    static List<Car> cars;
    static {
        try {
            cars= new CsvToBeanBuilder(new FileReader(fileName)).withType(Car.class).build().parse();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

and to start the webservice SoApplication.java:

package com.example.so;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SoApplication.class, args);
    }

}

The file with the data abc.csv:

id,name,price
1,Audi,52642
2,Mercedes,57127
3,Skoda,9000
4,Volvo,29000
5,Bentley,350000
6,Citroën,21000
7,Füll,41400
8,Rosé,21600
9,Toyota,26700

It works more or less fine, but when you enter http://localhost:8080/car/6, my browser (Firefox) displays "Citroën" instead of "Citroën". Reading in the csv seems to work fine, because when you print the bean using its .toString() you get Car{id=6, brand='Citroën', price=21000}. So apparently the json-conversion is the problem. What can I do to solve this issue?

I am new to world of java-web, so feel free telling me if there are some other problems with my approach.

Noskario
  • 378
  • 1
  • 9

1 Answers1

1

I don't think this is a problem with JSON conversion but with your character encoding. Make sure both your CSV file and the output to JSON are in the same encoding, it's probably best to use UTF8. If you explicitly set produces = APPLICATION_JSON_VALUE on your controller annotation, it should already use UTF8 for that. So if it then still fails, the question remains whether the CSV is in UTF8.

Also, if you don't know what I'm talking about, https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/ is pretty much a must-read.

Sebastiaan van den Broek
  • 5,818
  • 7
  • 40
  • 73
  • I do not quite understand where to put the `produces = APPLICATION_JSON_VALUE`. In which controller annotation? I know that there are different encodings, but I do not know where I should change that: In some controller annotation, in some settings of java, in the settings of the OS (I would not like to change that, I fear I could break something), in the settings of the browser? – Noskario Aug 10 '22 at 10:42
  • @Noskario If you don't have a @RequestMapping annotation on the controller, you can put it in the specific @GetMapping annotations, i.e. `@GetMapping(produces = APPLICATION_JSON_VALUE)`. As for your other question, I would really recommend reading that article. It's not a setting you're doing, the CSV may already be in a different encoding than what you're interpreting it as. – Sebastiaan van den Broek Aug 10 '22 at 10:59
  • The csv is in UTF-8. I tried it out in notepad++. Using the encoding UTF-8 everything is fine, using the encoding ANSI, the Citroën is displayed as Citroën. Adding the produces does not change anything... – Noskario Aug 10 '22 at 11:33
  • @Noskario you may need to explicitly tell the CSV library to load this CSV as UTF8. Because it might just grab the system/JVM default and that may not be UTF8. Although it's probably wise to set that to UTF8 as well, considering how standard that is nowadays. Look at https://stackoverflow.com/questions/361975/setting-the-default-java-character-encoding for that. – Sebastiaan van den Broek Aug 10 '22 at 12:55