5

Hi I am trying to parse a JSON that I have saved in a resource folder and test it. So I took these steps for now.

DataLoader.java

@Service
public class DataLoader {

private static ObjectMapper  objectMapper = defaultObjectMapper();

  private static ObjectMapper defaultObjectMapper(){
    ObjectMapper  defaultObjectMapper = new ObjectMapper();
    //defaultObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    return defaultObjectMapper;
  }

  public static JsonNode parse(String str) throws IOException {
    return objectMapper.readTree(str);
  }

  public static <A> A fromJason(JsonNode node, Class<A> clazz) throws JsonProcessingException {
    return objectMapper.treeToValue(node, clazz);
  }

}

DataLoaderTest.java

public class DataLoaderTest {

    @Value("classpath:data/novo.json")
    Resource jsonSource;

    //private String jsonSource = "{\"title\":\"new book\"}";

    @Test
    public void parse() throws IOException {
        JsonNode node = DataLoader.parse(jsonSource);
        assertEquals(node.get("title").asText(), "new book");
    }

    @Test
    public void fromJson() throws IOException {
        JsonNode node = DataLoader.parse(jsonSource);
        Fruit pojo = DataLoader.fromJason(node, Fruit.class);
        System.out.println("Pojo title " + pojo.title);
    }

}

So when I test it with //private String jsonSource = "{\"title\":\"new book\"}"; everything is working fine.

When I try to load JSON file from resources folder I am getting error:

error: incompatible types: Resource cannot be converted to String JsonNode node = ApxDataLoader.parse(jsonSource);

Any help highly appreciated.

2 Answers 2

8

with Spring-boot, the easy way to load a json in the classpath (for example in the resources folder) would be :

File jsonFile = new ClassPathResource("data.json").getFile();
// or
File jsonFile = jsonResource.getFile();

JsonNode node = objectMapper.readTree(jsonFile);

No need to deal with InputStream, Spring takes care of that for you. and Jackson can read a File directly, so no need for a String neither.

No need to deal with JsonNode neither: You can also even further optimize the readability of the code by doing all the parsing/mapping at the same time :

Fruit myFruit = objectMapper.readValue(jsonFile, Fruit.class);

If you still need the contents of the file as a String for some reason:

String jsonString = Files.readString(jsonFile.toPath()); // default charset of readString is UTF8 

DataLoader could have only one method:

public class DataLoader {

  // ... objectmapper stuff ...

  public static <A> A fromJason(Resource jsonResource, Class<A> clazz) throws JsonProcessingException {
    return objectMapper.readValue(jsonResource.getFile(), clazz);
  }
Sign up to request clarification or add additional context in comments.

Comments

1

The Resource object is not a string. To parse it to the appropriate JSON structure, you would have to read the Resource. See: https://www.baeldung.com/spring-load-resource-as-string

Here's: The relevant part copied from the article.

public static String asString(Resource resource) {
        try (Reader reader = new InputStreamReader(resource.getInputStream(), UTF_8)) {
            return FileCopyUtils.copyToString(reader);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

Which should give you the string read from the Resource.

Another option you have is to use the InputStream from the resource and pass it to the overloaded readTree() method that can take an input stream.

See : https://fasterxml.github.io/jackson-databind/javadoc/2.7/com/fasterxml/jackson/databind/ObjectMapper.html#readTree(java.io.InputStream)

I would recommend the second approach instead of reading the whole file as a String and then passing it to the ObjectMapper.

2 Comments

Ok, yes. Thank you for your answer. Where do I put this class? If you take a look at my parse function in DataLoader class you will see that I am sending String. Is something that I have to change there maybe?
You can change the method Dataloader::parse(Str) to Dataloader::parse(InputStream) and pass Resource.getInputStream() to it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.