It looks like You have more than one org.json:json dependency on your classpath.
Looking at it:org.springframework.boot:spring-boot-starter-test depends on
com.jayway.jsonpath:json-pathwhich in turn brings org.json:json which is much older than your version (v. 20140107)
You could try excluding this transitive dependency from spring-boot-starter-test:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</exclusion>
</exclusions>
</dependency>
... but it's possible that there is something within json-path which depends on something from the older json library, which is no longer in the newer version, so proceed with caution and test everything thoroughly.
There is also a chance that something else brings org.json:json.
To verify, please run mvn dependency:tree and search in the produced output for org.json:json.
Videos
It looks like You have more than one org.json:json dependency on your classpath.
Looking at it:org.springframework.boot:spring-boot-starter-test depends on
com.jayway.jsonpath:json-pathwhich in turn brings org.json:json which is much older than your version (v. 20140107)
You could try excluding this transitive dependency from spring-boot-starter-test:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</exclusion>
</exclusions>
</dependency>
... but it's possible that there is something within json-path which depends on something from the older json library, which is no longer in the newer version, so proceed with caution and test everything thoroughly.
There is also a chance that something else brings org.json:json.
To verify, please run mvn dependency:tree and search in the produced output for org.json:json.
The version definition (<version>RELEASE</version>) of your spring boot parent is incorrect.
The correct way to define a spring boot parent is -
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath />
</parent>
I tried with your code with a sample spring boot project and I get the error,
No converter for [class org.json.JSONObject]
The reason for this error is explained clearly here. To reiterate the answer, JSONObject classes don't have getters and hence the error. By default spring-boot starter web dependency has Jackson web support which can convert any POJO class to JSON object. So as the answer by @süleyman-can using a POJO is the right way to handle this.
In case, you can't use a POJO class because the fields in the response will be different for each request. For example, you have to send
{"a": "b"}
for one response and
{"c": "d"}
for another response, you can always use Map<String, String> like this,
@RequestMapping(value = "/test", method = RequestMethod.GET)
@ResponseBody
public Map<String, String> test() {
Map<String, String> test = new HashMap<>();
test.put("name","caroline");
return test;
}
and the response would come like this,
{"name":"caroline"}
I hope you are talking about org.json package
If you really want to use JSONObject to create your JSON, then the following code works. It's just that you can change the return type from JSONObject to String.
@RequestMapping(value = "/test", method = RequestMethod.GET)
@ResponseBody
public String Test() {
JSONObject test = new JSONObject();
test.put("name","caroline");
return test.toString();
}
Spring Boot's auto-configuration for Jackson requires spring-web as it's the Spring Framework module that contains the infrastructure for configuring and creating a Jackson ObjectMapper. If you really don't want a spring-web dependency in your application, you could replace the dependency on spring-boot-starter-json with a direct dependency on Jackson instead, however you will then have to configure and create the ObjectMapper yourself as Spring Boot will no longer do it for you.
I created a custom jackson standalone configuration.
It only contains what I need, but you could easily copy the bits in the JacksonAutoConfiguration for the jacksonProperties or anything else that you need and add them here. And then remove the JacksonAutoConfiguration class and use the code snippet below.
I just wanted to keep it simple because mine was for a redis synchronization service.
The optimal solution would be to rewrite the code in JacksonAutoConfiguration and drop the Jackson2ObjectMapper and use JsonMapper.builder() instead and then they could drop the spring-web dependency entirely.
@Configuration
public class JacksonStandaloneConfiguration {
@Bean
public ObjectMapper jacksonOjectMapper(ObjectProvider<Module> provider) {
// All modules declared as beans anywhere else
List<Module> modulesToInstall = provider.stream().toList();
Builder builder = JsonMapper.builder();
ObjectMapper mapper = configure(builder);
registerModules(mapper, modulesToInstall);
return mapper;
}
private ObjectMapper configure(Builder builder) {
return builder //
// Spring boot defaults
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) //
.disable(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS) //
// Jackson2ObjectMapperBuilder defaults
.disable(MapperFeature.DEFAULT_VIEW_INCLUSION) //
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) //
.build();
}
private static void registerModules(ObjectMapper mapper, List<Module> modulesToInstall) {
MultiValueMap<Object, Module> modulesToRegister = new LinkedMultiValueMap<>();
registerWellKnownModulesIfAvailable(modulesToRegister);
modulesToInstall.forEach(module -> registerModule(module, modulesToRegister));
List<Module> modules = new ArrayList<>();
for (List<Module> nestedModules : modulesToRegister.values()) {
modules.addAll(nestedModules);
}
mapper.registerModules(modules);
}
private static void registerWellKnownModulesIfAvailable(MultiValueMap<Object, Module> modulesToRegister) {
// Jackson2ObjectMapperBuilder defaults (You could add these as beans and remove this method entirely)
registerModule(new Jdk8Module(), modulesToRegister);
registerModule(new JavaTimeModule(), modulesToRegister);
// registerModule(new JodaModule(), modulesToRegister);
// registerModule(new KotlinModule(), modulesToRegister);
}
private static void registerModule(Module module, MultiValueMap<Object, Module> modulesToRegister) {
if (module.getTypeId() == null) {
modulesToRegister.add(SimpleModule.class.getName(), module);
} else {
modulesToRegister.set(module.getTypeId(), module);
}
}
}
Add under
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
The following exclusion:
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
</exclusions>
Similarly, for Gradle projects:
testCompile("org.springframework.boot:spring-boot-starter-test") {
exclude group: "com.vaadin.external.google", module:"android-json"
}
Background:
org.json works great, but has a license clause that some people don't like ("The Software shall be used for Good, not Evil."). So Vaadin wanted to use the library, but couldn't be sure they wouldn't use it for evil someday. Instead, they re-implemented the interface, published android-json and used it as a drop in replacement for org.json. Others began to use android-json as well so that they too would not be bound by the requirement of not using their software for evil.
This is a fine solution, except that when the two libraries are on the classpath, they collide.
Solution:
If you get this error from conflicting transitive dependencies, then your best bet is to exclude either Vaadin's android-json library (brought in by Spring), or exclude the org.json library (brought in by another dependency). Vaadin's version is meant to be an identical implementation, but there are subtle differences.
If you're using org.json in your code and it is conflicting with Spring's Vaadin dependency, then I would recommend trying open-json. It's a port of Vaadin's re-implementation of org.json, but they changed the packages so you won't have any conflicts with org.json:json or com.vaadin.external.google:android-json
https://github.com/openjson/openjson
Add gradle dependency:
implementation('com.github.openjson:openjson:1.0.12')
Or in Maven:
<dependency>
<groupId>com.github.openjson</groupId>
<artifactId>openjson</artifactId>
<version>1.0.12</version>
</dependency>
Then update any imports that were being used by org.json classes.