parsing json file error whith jackon-mapper - java

I want parse this json structure
I inspierer this tutorial [how parse json file with jackson in android][http://www.tutos-android.com/parsing-json-jackson-android]
"Categorie": [
{
"typecategorie" : "Country",
"valeurcategorie": ["Afghanistan","Albania","Zambia","Zimbabwe"]
},
{
"typecategorie": "Year",
"valeurcategorie": ["1911","1912","1913","1960","1961","1962","1963",,"2054"]
},
{
"typecategorie": "Number",
"valeurcategorie": ["1","2","3","4","5","6","7","8","9","10","11"]
}]
I use this class
public class Categorie {
private String typecategorie;
private List<String> valeurcategorie;
public Categorie(){
super();
this.typecategorie = "";
this.valeurcategorie = new ArrayList<String>();
}
public Categorie(String typecategorie,ArrayList<String> valeurcategorie ){
super();
this.typecategorie = typecategorie;
this.valeurcategorie.addAll(valeurcategorie);
}
public List<String> getValCategorie(){
return this.valeurcategorie;
}
public String gettypecategorie(){
return typecategorie;
}
public void settypecategorie(String typecategorie){
this.typecategorie = typecategorie;
}
}
and this code for load my object
public void LoadJson(String fileName) {
try {
LoadFile(fileName);
// InputStream inputStream = urlConnection.getInputStream();
jp = jsonFactory.createJsonParser(jsonFile);
categories = objectMapper.readValue(jp, Categories.class);
categorieList = categories.get("categorie");
} catch (JsonParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
but I get this error code
org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "valeurcategorie" (Class fr.lilperso.worldcupquizz.Categorie), not marked as ignorable
at [Source: /mnt/sdcard/worldCupQuizz/categorie.json; line: 5, column: 24] (through reference chain: fr.lilperso.worldcupquizz.Categorie["valeurcategorie"])

You need a setter for valeurcategorie. Add this to your Categories class:
public void setValeurcategorie(List<String> valeurcategorie) {
this.valeurcategorie = valeurcategorie;
}

You are trying to deserialize a list/array as a single object with
categories = objectMapper.readValue(jp, Categories.class);
Instead of above Categories.class, you must use Categories[].class if you are using an array or the TypeReference for list. See
How to use Jackson to deserialise an array of objects

Related

Gson append object to json file

I am currently working on a todo web application using Spring Boot. The problem I'm facing is that whenever I add an item it is not stored in my json file. This is my current json file:
[
{
"id": 0,
"task": "some task"
},
{
"id": 1,
"task": "some other task"
},
{
"id": 2,
"task": "some different task"
}
]
When I add my todo item with the application, it gets added to my dataprovider;
TodoDataProvider.java:
public class TodoDataProvider {
private static TodoDataProvider instance;
private List<TodoItem> todoItems = new ArrayList<>();
public static TodoDataProvider getInstance() {
if (instance == null) {
instance = new TodoDataProvider();
}
//read data from json
Gson gson = new Gson();
try {
FileReader reader = new FileReader("src/main/java/com/example/servingwebcontent/todos.json");
TodoItem[] tempTodos = gson.fromJson(reader, TodoItem[].class);
for (TodoItem tempTodo : tempTodos) {
instance.addTodo(tempTodo);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return instance;
}
... getters and setters
After I try to add this todo my json file becomes empty. What is the best way to add this new json object to the existing json file using gson?
This is the code where I add this item:
TodoController.java
#Controller
public class TodoController {
TodoDataProvider dataProvider = TodoDataProvider.getInstance();
#GetMapping("/")
public String greeting(Model model) {
model.addAttribute("todos", dataProvider.getTodoItems());
return "todo";
}
#PostMapping("/")
public String addTodo(Model model, #RequestParam("todoTask") String todoTask) {
TodoItem todoItem = new TodoItem(4, todoTask);
dataProvider.addTodo(todoItem);
Gson gson = new Gson();
try {
// TODO: 14-7-2022 add to json instead of replace
gson.toJson(dataProvider.getTodoItems(), new FileWriter("src/main/java/com/example/servingwebcontent/todos.json"));
} catch (IOException e) {
System.out.println(e.getMessage());
}
model.addAttribute("todos", dataProvider.getTodoItems());
return "redirect:/";
}
}

Identify JsonObject vs JsonArray using Gson

I have the following validator which checks if a JSON string is valid using Gson. It works well with a JSON object but it blows up when you pass it a JSON array.
JsonStringValidator
public class JsonStringValidator implements ConstraintValidator<JsonString, String> {
private static final TypeAdapter<JsonObject> strictGsonObjectAdapter =
new Gson().getAdapter(JsonObject.class);
#Override
public boolean isValid(String jsonString, ConstraintValidatorContext context) {
try {
try (JsonReader reader = new JsonReader(new StringReader(jsonString))) {
strictGsonObjectAdapter.read(reader);
reader.hasNext();
return true;
}
} catch (IOException e) {
return false;
}
}
}
Works
{
"books":[
{
"isbn": "12345"
}
]
}
Fails
[
{
"isbn": "12345"
}
]
Exception
com.google.gson.JsonSyntaxException: Expected a com.google.gson.JsonObject but was com.google.gson.JsonArray
So it seems like I also need a strictGsonArrayAdapter.
But how can I determine if it's an array or object before calling strictGsonObjectAdapter?
I was able to determine whether the JSON string was an array or an object by using JsonParser to give me a JsonElement.
The JsonElement class has boolean methods for isJsonArray() and isJsonObject().
JsonElement jsonElement = JsonParser.parseString(jsonString);
log.info(jsonElement.isJsonArray());
log.info(jsonElement.isJsonObject());

deserialize Json file to java Object that contains a map with an object as key

I am struggling to find a way to read a json file that need to fit into a Map.
So, I have a class ingredients that only contains a String variable ingredient. In another class that is called Recipe I have a Map that will track the ingredients and the amount needed for that particular recipe and a String for the name of the Recipe.
public class Recipe implements Serializable{
private String name;
private Map<Ingredients,Integer> ingredientsList = new HashMap<>();
public Recipe() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Map<Ingredients, Integer> getIngredientsList() {
return ingredientsList;
}
public void setIngredientsList(Map<Ingredients, Integer> ingredientsList) {
this.ingredientsList = ingredientsList;
}
#Override
public String toString() {
return "Recipe{" +
"name='" + name + '\'' +
", ingredientsList=" + ingredientsList +
'}';
}
}
I have a testClass that contains two methods one to write my recipe to a json file and one to read It from the same json file
#Test
public void writeToJsonFile(){
Ingredients pasta = new Ingredients();
pasta.setName("pasta");
Ingredients bolognaise = new Ingredients();
bolognaise.setName("bolognaise");
Map<Ingredients,Integer>ingredientsIntegerMap = new HashMap<>();
ingredientsIntegerMap.put(pasta,500);
ingredientsIntegerMap.put(bolognaise,600);
Recipe spaghetti = new Recipe();
spaghetti.setName("spaghetti");
spaghetti.setIngredientsList(ingredientsIntegerMap);
Gson gson = new Gson();
try {
FileWriter writer = new FileWriter("src/test/resources/recipe1.json");
writer.write(gson.toJson(spaghetti));
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
#Test
public void readFromJsonFile(){
Gson gson = new Gson();
try {
BufferedReader buffer = new BufferedReader(new FileReader("src/test/resources/recipe1.json"));
Recipe dish =gson.fromJson(buffer, Recipe.class);
System.out.println(dish);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Now my issue is the following when I create a recipe that contains some ingredient and save it to a json fill I don’t have any issue everything works but when I want to load the created Jason file to a recipe it doesn’t work.
this is the error message i get when i try to read the Json file
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 4 column 6 path $.ingredientsList.
Here the Created Json file that contain the recipe
{
"name":"spaghetti",
"ingredientsList":{
"Ingredients{name\u003d\u0027pasta\u0027}":500,
"Ingredients{name\u003d\u0027bolognaise\u0027}":600
}
}
the issue occur due to the Map in the Recipe Class when i remove it or replace it by a List everything works but i would like to use a Map.
can someone help on this issue or recommend another way to track the amount of ingredient for a recipe
thanks
It is a little bit weird that you put as a key in Map an Object that doesn't contain any unique identifier. Maybe it will be better to change Ingredients class to an enum like the following:
public enum Ingredients {
PASTA,
BOLOGNAISE
}
Your JSON will change to:
{
"name":"spaghetti",
"ingredientsList":{
"PASTA":500,
"BOLOGNAISE":600
}
}
Or create an aggregate Object like:
public class IngredientQuantity {
private Ingredient ingredient;
private double quantity;
}
class Ingredient {
private String name;
}
And then replace your map with a simple list:
{
"name": "spaghetti",
"ingredientsList": [
{
"ingredient": {
"name": "PASTA"
},
"quantity": 500
},
{
"ingredient": {
"name": "BOLOGNAISE"
},
"quantity": 600
}
]
}

How to use JSON with difficult objects

I have problem with dynamic JSON data. I don't know how to put it into my JAVA class. I need "routes" data. But i don't know what i should do with this ""2019-05-27": {...".
It is part of JSON file...
{
"2019-05-26": {
"lastUpdate": "2019-05-26 06:05:02",
"routes": [
{
"routeId": 107,
"agencyId": 18
},
{
"routeId": 222,
"agencyId": 22
}
]
},
"2019-05-27": {
"lastUpdate": "2019-05-27 06:05:02",
"routes": [
{
"routeId": 33,
"agencyId": 14
},
{
"routeId": 345,
"agencyId": 2232
}
]
}
}
The code below doesn't work. It is not Map<String,Map<String, String>>. I think it is -
Gson gson = new Gson();
Type mapType = new TypeToken<Map<String,Map<String, String>>>() {}.getType();
Map<String,Map<String, String>> map = null;
try {
map = gson.fromJson(new FileReader("routes.json"), mapType);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
What should I do to take this data ?
Create POJO classes like that :
public class MyObject {
private List<Route> routes;
private String lastUpdate;
public MyObject(List<Route> routes, String lastUpdate) {
this.routes = routes;
this.lastUpdate = lastUpdate;
}
// assume getters and setters
}
public class Route {
private String routeId;
private String agencyId;
public Route(String routeId, String agencyId) {
this.routeId = routeId;
this.agencyId = agencyId;
}
// assume getters and setters
}
To test it :
public static void main(String[] args) throws IOException {
Gson gson = new Gson();
String json = Files.lines(Paths.get("src/main/resources/data.json")).collect(Collectors.joining());
Type mapType = new TypeToken<Map<String, MyObject>>() {}.getType();
Map<String, MyObject> map = gson.fromJson(json, mapType);
map.forEach((s, myObject) -> System.out.println(s + " " + myObject.getLastUpdate()));
}
The output is :
2019-05-26 2019-05-26 06:05:02
2019-05-27 2019-05-27 06:05:02
You just need to create a map which has date as a key and custom object as value.
Please check this line :
json = Files.lines(Paths.get("routes.json")).collect(Collectors.joining());
this line may store null value and that's why you are getting a java.lang.NullPointerException.
Please check this by debugging. I think you will get the solution.

can I set json to be pretty print only in some attributes?

I have a json with many attributes.
I want some of them to be inline. Meaning with no new break lines.
Here is my code today:
private String serializeToJson(T item) {
String json;
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
try {
json = ow.writeValueAsString(item);
} catch (IOException e) {
e.printStackTrace();
json = "";
}
return json;
}
how can I set it to be not "pretty print" for attribute path like this { "path" : { "segmentId" : 31788674, "nodeId" : 26161441, "x" : -74.236605 ...
I serialized this specific property to inline json string separately.
public ResultUiShort(ResultLong result) {
this.path = stringUtils.toInlineJson(result.path);
...
}
and
public <T> String toInlineJson(T item) {
String json;
ObjectWriter ow = new ObjectMapper().writer();
try {
json = ow.writeValueAsString(item);
} catch (IOException e) {
e.printStackTrace();
json = "";
}
return json;
}

Categories