Skip to content

Commit

Permalink
get rid of org.json so we can be evil
Browse files Browse the repository at this point in the history
  • Loading branch information
ryber committed Sep 22, 2019
1 parent f9e4810 commit d5ab3b6
Show file tree
Hide file tree
Showing 21 changed files with 81 additions and 50 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 3.0.0
Replace the dependency on org.json with a native kong.unirest library powered by gson. See the Upgrade Guide for details.

## 2.4.00 (pending)
* add an entire new return type: ```asBytes()``` (as well as async versions) will return a raw byte[] array.

Expand Down
30 changes: 24 additions & 6 deletions UPGRADE_GUIDE.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,32 @@
# Upgrade Guide

## Upgrading to Unirest 3.0
The primary difference in Unirest 3 is that the org.json dependency has been replaced by a clean-room implementation of the it's interface using Google Gson as the engine. This was done due to conflicts with the org.json license which requires that "The Software shall be used for Good, not Evil.". While many people would rightly view this as silly and unenforceable by law, many organizations such as Eclipse, Debian, and Apache will not allow linking to it.
The primary difference in Unirest 3 is that the org.json dependency has been replaced by a clean-room implementation of the it's interface using Google Gson as the engine.

### What? Why?
This was done due to conflicts with the org.json license which requires that "The Software shall be used for Good, not Evil.". While many people would rightly view this as silly and unenforceable by law, many organizations such as Eclipse, Debian, and Apache will not allow using it.

### Why not switch to the google implementation of org.json?
Several reasons:
* It has not been maintained in several years and no longer matches the org.json signatures.
* It causes classpath conflicts which many projects forbid.
* We would like Unirest to be able to expand beyond org.json and offer more advanced native features like object mapping.

### Why Gson and not Jackson?
* Gson is closest in spirit and method signature to org.json and was deemed quicker to adopt.
* It's small, mature and a single dependency.
* It would conflict less in other projects than Jackson would which is both more popular and far more complex.

### How was this done?
Implementation was done without looking at the internals of the org.json classes. This was accomplished by writing extensive unit tests in order to document behavior and method signatures and then simply changing the test to use this projects own classes as well as Google Gson.

### Differences between org.json and kong.unirest.json
For the most part kong.unirest.json honors all public interfaces and behavior of ```JSONArray``` and ```JSONObject```. The utility classes in org.json have NOT been implemented as they are not required for Unirest's use case. Implementation was done without looking at the internals of the org.json classes. This was accomplished by writing extensive unit tests in order to document behavior and method signatures and then simply changing the test to use this projects own classes as well as Google Gson. There are however differences:
* The namespace ```kong.unirest.json```
* The namespace is now ```kong.unirest.json```
* For the most part kong.unirest.json honors all public interfaces and behavior of ```JSONArray```, ```JSONObject```, and ```JSONPointer```.
* The utility classes in org.json have NOT been implemented as they are not required for Unirest's use case. So things like XML-to-JSON, and CSV-to-JSON have not been implemented.
* Custom indenting with ```.toString(int spaces)``` does not honor the indent factor and always uses 2 spaces. Waiting on https://github.com/google/gson/pull/1280 for a fix.
* There are some slight differences in the details of some error messages.
* ```optString``` and ```getString``` methods no longer throw an exception when the value is not a string but will simply convert the value to a string.
* when you ```put``` to a JSONArray org.json appears to store original object and only turns it to Json on serialization meaning you may also ```get``` it back. This library turns everything to a gson JsonElement immediately on ```put```.
* ```JSONPointer(List<String> strings)``` has not been implemented. It's not documented and seems to assume knowledge of the internals of the class.


## Upgrading to Unirest 2.0 from previous versions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public class GsonObjectMapperTest {
private GsonObjectMapper om = new GsonObjectMapper();

@Test
public void canWrite() {
public void canWrite() throws Exception {
TestMe test = new TestMe("foo", 42, new TestMe("bar", 666, null));

String json = om.writeValue(test);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ a copy of this software and associated documentation files (the
*/
package kong.unirest;

import org.json.JSONException;
import org.junit.Test;
import org.skyscreamer.jsonassert.JSONAssert;

Expand All @@ -60,7 +61,7 @@ public class JacksonObjectMapperTest {
private JacksonObjectMapper om = new JacksonObjectMapper();

@Test
public void canWrite() {
public void canWrite() throws JSONException {
TestMe test = new TestMe("foo", 42, new TestMe("bar", 666, null));

String json = om.writeValue(test);
Expand Down
5 changes: 0 additions & 5 deletions unirest/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@
</exclusions>
</dependency>

<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
4 changes: 2 additions & 2 deletions unirest/src/main/java/kong/unirest/HttpRequestBody.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@

package kong.unirest;

import org.json.JSONArray;
import org.json.JSONObject;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;

import java.io.File;
import java.io.InputStream;
Expand Down
4 changes: 2 additions & 2 deletions unirest/src/main/java/kong/unirest/HttpRequestWithBody.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@

package kong.unirest;

import org.json.JSONArray;
import org.json.JSONObject;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;

import java.io.File;
import java.io.InputStream;
Expand Down
6 changes: 3 additions & 3 deletions unirest/src/main/java/kong/unirest/JsonNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@

package kong.unirest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONException;
import kong.unirest.json.JSONObject;

public class JsonNode {

Expand Down
4 changes: 2 additions & 2 deletions unirest/src/main/java/kong/unirest/JsonPatch.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@

package kong.unirest;

import org.json.JSONArray;
import org.json.JSONObject;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;

import java.util.ArrayList;
import java.util.Collections;
Expand Down
2 changes: 1 addition & 1 deletion unirest/src/main/java/kong/unirest/JsonPatchItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

package kong.unirest;

import org.json.JSONObject;
import kong.unirest.json.JSONObject;

import java.util.Objects;

Expand Down
22 changes: 14 additions & 8 deletions unirest/src/main/java/kong/unirest/json/JSONObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,21 @@ public static Object wrap(Object obj) {
return new JSONArray((Collection)obj);
}
if(obj.getClass().isArray()){
JSONArray array = new JSONArray();
int length = Array.getLength(obj);
for (int i = 0; i < length; i ++) {
Object arrayElement = Array.get(obj, i);
array.put(arrayElement);
}
return array;
return wrapArray(obj);
}
return new JSONObject();
}

private static JSONArray wrapArray(Object obj) {
JSONArray array = new JSONArray();
int length = Array.getLength(obj);
for (int i = 0; i < length; i ++) {
Object arrayElement = Array.get(obj, i);
array.put(arrayElement);
}
return array;
}

private static boolean isPrimitive(Object o){
return (o instanceof String
|| o instanceof Number
Expand Down Expand Up @@ -831,8 +835,10 @@ public JSONObject put(String key, Object value) throws JSONException {
put(key, (JSONObject) value);
} else if (value instanceof Map){
put(key, (Map) value);
} else if (value instanceof Collection){
} else if (value instanceof Collection) {
put(key, (Collection) value);
} else if (value.getClass().isArray()){
put(key, wrapArray(value));
} else {
put(key, String.valueOf(value));
}
Expand Down
7 changes: 7 additions & 0 deletions unirest/src/main/java/kong/unirest/json/JSONPointer.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
/**
* A Json Pointer query object following
* https://tools.ietf.org/html/rfc6901
*
*/
public class JSONPointer {

Expand Down Expand Up @@ -103,6 +104,12 @@ private static JSONPointer createPointer(String query) {
return compileNext(query);
}

/**
* Many of the path compiling code was borrowed from Jackson.
* It is, slightly modified but similar enough to give credit.
* please see com.fasterxml.jackson.core.JsonPointer
* @author Tatu Saloranta
*/
private static JSONPointer compileNext(String query) {
final int end = query.length();
for (int i = 1; i < end; ) {
Expand Down
4 changes: 2 additions & 2 deletions unirest/src/test/java/BehaviorTests/AsJsonTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void failureToReturnValidJsonWillResultInAnEmptyNode() {
assertNull(response.getBody());
UnirestParsingException ex = response.getParsingError().get();
assertEquals("You did something bad", ex.getOriginalBody());
assertEquals("org.json.JSONException: A JSONArray text must start with '[' at 1 [character 2 line 1]",
assertEquals("kong.unirest.json.JSONException: Invalid JSON",
response.getParsingError().get().getMessage());

}
Expand All @@ -93,7 +93,7 @@ public void failureToReturnValidJsonWillResultInAnEmptyNodeAsync() {
assertEquals(400, response.getStatus());
assertNull(response.getBody());
assertEquals(null, response.getBody());
assertEquals("org.json.JSONException: A JSONArray text must start with '[' at 1 [character 2 line 1]",
assertEquals("kong.unirest.json.JSONException: Invalid JSON",
response.getParsingError().get().getMessage());

}));
Expand Down
2 changes: 1 addition & 1 deletion unirest/src/test/java/BehaviorTests/DefectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.nio.client.HttpAsyncClient;
import org.json.JSONObject;
import kong.unirest.json.JSONObject;
import org.junit.Ignore;
import kong.unirest.Unirest;
import org.junit.Test;
Expand Down
6 changes: 3 additions & 3 deletions unirest/src/test/java/BehaviorTests/JsonPatchTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@

import com.google.common.collect.ImmutableMap;
import kong.unirest.Unirest;
import org.json.JSONArray;
import org.json.JSONObject;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;
import org.junit.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import kong.unirest.TestUtil;
Expand Down Expand Up @@ -141,7 +141,7 @@ public void canCopyObjects() {
}

@Test
public void thatsSomeValidJson() throws IOException {
public void thatsSomeValidJson() throws Exception {
String patch = Unirest.jsonPatch(MockServer.PATCH)
.add("/fruits/-", "Apple")
.remove("/bugs")
Expand Down
4 changes: 2 additions & 2 deletions unirest/src/test/java/BehaviorTests/UniBodyPostingTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
import kong.unirest.MockCallback;
import kong.unirest.Unirest;
import kong.unirest.UnirestConfigException;
import org.json.JSONArray;
import org.json.JSONObject;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;
import org.junit.Test;

import java.nio.charset.StandardCharsets;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import org.json.JSONObject;
import kong.unirest.json.JSONObject;

import java.io.File;
import java.io.IOException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
package kong.unirest;

import BehaviorTests.RequestCapture;
import org.json.JSONException;
import org.junit.Test;
import org.skyscreamer.jsonassert.JSONAssert;

Expand All @@ -34,7 +35,7 @@ public class JacksonObjectMapperTest {
private JacksonObjectMapper om = new JacksonObjectMapper();

@Test
public void jsonPatch() {
public void jsonPatch() throws JSONException {
JsonPatch patch = new JsonPatch();
patch.add("/foo", "bar");
patch.add("/baz", "qux");
Expand All @@ -48,7 +49,7 @@ public void jsonPatch() {
}

@Test
public void jsonPatchInRequestCapture() {
public void jsonPatchInRequestCapture() throws JSONException {
JsonPatch patch = new JsonPatch();
patch.add("/foo", "bar");
patch.add("/baz", "qux");
Expand Down
4 changes: 2 additions & 2 deletions unirest/src/test/java/kong/unirest/json/JSONArrayTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ public void strings() {
}

@Test
public void jsonObjects() {
public void jsonObjects() throws Exception {
JSONObject subObj = new JSONObject("{\"derp\": 42}");
JSONArray obj = new JSONArray();
assertSame(obj, obj.put(subObj));
Expand All @@ -274,7 +274,7 @@ public void jsonObjects() {
}

@Test
public void jsonArrays() {
public void jsonArrays() throws Exception {
JSONArray subObj = new JSONArray("[42]");
JSONArray obj = new JSONArray();
assertSame(obj, obj.put(subObj));
Expand Down
6 changes: 3 additions & 3 deletions unirest/src/test/java/kong/unirest/json/JSONObjectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ public void strings() {
}

@Test
public void jsonObjects() {
public void jsonObjects() throws Exception {
JSONObject subObj = new JSONObject("{\"derp\": 42}");
JSONObject obj = new JSONObject();
obj.put("key", subObj);
Expand All @@ -238,7 +238,7 @@ public void jsonObjects() {
}

@Test
public void jsonArrays() {
public void jsonArrays() throws Exception {
JSONArray subObj = new JSONArray("[42]");
JSONObject obj = new JSONObject();
obj.put("key", subObj);
Expand Down Expand Up @@ -591,7 +591,7 @@ public static void assertJSONEx(TestUtil.ExRunnable exRunnable, String message)
assertException(exRunnable, JSONException.class, message);
}

public static void assertEqualJson(Object subObj, Object value) {
public static void assertEqualJson(Object subObj, Object value) throws org.json.JSONException {
JSONAssert.assertEquals(subObj.toString(), value.toString(), true);
}

Expand Down
6 changes: 3 additions & 3 deletions unirest/src/test/java/kong/unirest/json/JSONPointerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,12 @@ public void elementInObjectDoesNotExist() {
}

@Test
public void testRef_all() {
public void testRef_all() throws Exception {
assertQueryJson(RFC_TEST, "");
}

@Test
public void testRef_Array(){
public void testRef_Array() throws Exception {
assertQueryJson("[\"bar\", \"baz\"]", "/foo");
}

Expand Down Expand Up @@ -167,7 +167,7 @@ public void builder(){
pointer.toString());
}

private void assertQueryJson(String s, String s2) {
private void assertQueryJson(String s, String s2) throws Exception {
JSONAssert.assertEquals(s, obj.query(s2).toString(), true);
}

Expand Down

0 comments on commit d5ab3b6

Please sign in to comment.