Skip to content

Commit

Permalink
Merge pull request #46 from bowbahdoe/cleanup-march-1
Browse files Browse the repository at this point in the history
Add more docs
  • Loading branch information
bowbahdoe authored Mar 1, 2023
2 parents e094dab + b408517 commit d856332
Show file tree
Hide file tree
Showing 8 changed files with 1,046 additions and 12 deletions.
780 changes: 777 additions & 3 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>dev.mccue</groupId>
<artifactId>json</artifactId>
<version>0.2.1</version>
<version>0.2.2</version>
<packaging>jar</packaging>

<properties>
Expand Down
3 changes: 0 additions & 3 deletions src/main/java/dev/mccue/json/JsonArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
* Represents an array in the json data model.
Expand All @@ -19,8 +18,6 @@ static JsonArray of(Json... values) {
}

static JsonArray of(List<Json> value) {
Objects.requireNonNull(value, "Json.Array value must be nonnull");
value.forEach(json -> Objects.requireNonNull(json, "Each value in a Json.Array must be nonnull"));
return new ArrayImpl(List.copyOf(value));
}

Expand Down
13 changes: 12 additions & 1 deletion src/main/java/dev/mccue/json/JsonDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,17 @@ static <T> T null_(Json json) throws JsonDecodeException {
}
}

static <T> T null_(Json json, T value) throws JsonDecodeException {
if (!(json instanceof JsonNull)) {
throw JsonDecodeException.of(
"expected null",
json
);
} else {
return value;
}
}

static <T> JsonDecoder<List<T>> array(JsonDecoder<? extends T> itemDecoder) throws JsonDecodeException {
return json -> array(json, itemDecoder);
}
Expand Down Expand Up @@ -420,7 +431,7 @@ static <T> JsonDecoder<T> nullable(JsonDecoder<? extends T> decoder, T defaultVa
return json -> JsonDecoder.oneOf(
json,
decoder,
__ -> defaultValue
JsonDecoder.of(JsonDecoder::null_).map(__ -> defaultValue)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* freely.
* </p>
*
* @param json
* @param json A string representation of the JSON being serialized.
*/
public record JsonSerializationProxy(String json) implements Serializable {
@Serial
Expand Down
128 changes: 126 additions & 2 deletions src/test/java/dev/mccue/json/JsonDecoderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import org.junit.jupiter.api.Test;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.*;

public class JsonDecoderTest {
@Test
Expand Down Expand Up @@ -84,4 +86,126 @@ static Person fromJson(Json json) {
)
);
}

@Test
public void nullableDecoderTest() {
assertEquals(
Optional.of("abc"),
JsonDecoder.nullable(JsonDecoder::string)
.decode(JsonString.of("abc"))
);
assertEquals(
Optional.empty(),
JsonDecoder.nullable(JsonDecoder::string)
.decode(JsonNull.instance())
);
assertThrows(
JsonDecodeException.class,
() -> JsonDecoder.nullable(JsonDecoder::string)
.decode(JsonArray.of())
);

assertEquals(
"abc",
JsonDecoder.nullable(JsonDecoder::string, null)
.decode(JsonString.of("abc"))
);
assertNull(JsonDecoder.nullable(JsonDecoder::string, null)
.decode(JsonNull.instance()));
assertEquals(
"def",
JsonDecoder.nullable(JsonDecoder::string, "def")
.decode(JsonNull.instance())
);
assertThrows(
JsonDecodeException.class,
() -> JsonDecoder.nullable(JsonDecoder::string, null)
.decode(JsonArray.of())
);
}

@Test
public void booleanDecoderTest() {
assertTrue(JsonDecoder.boolean_(JsonTrue.instance()));
assertFalse(JsonDecoder.boolean_(JsonFalse.instance()));
assertThrows(
JsonDecodeException.class,
() -> JsonDecoder.boolean_(JsonString.of("abc"))
);
}

@Test
public void stringDecoderTest() {
assertEquals("abc", JsonDecoder.string(JsonString.of("abc")));
assertThrows(
JsonDecodeException.class,
() -> JsonDecoder.string(JsonNull.instance())
);
}

@Test
public void intDecoderTest() {
assertEquals(1, JsonDecoder.int_(Json.of(1)));
assertEquals(2, JsonDecoder.int_(Json.of(2L)));
assertEquals(3, JsonDecoder.int_(Json.of(new BigInteger("3"))));
assertEquals(4, JsonDecoder.int_(Json.of(new BigDecimal("4"))));
assertThrows(
JsonDecodeException.class,
() -> JsonDecoder.int_(Json.of(Long.MAX_VALUE))
);
assertThrows(
JsonDecodeException.class,
() -> JsonDecoder.int_(Json.of("abc"))
);
}

@Test
public void longDecoderTest() {
assertEquals(1L, JsonDecoder.long_(Json.of(1)));
assertEquals(2L, JsonDecoder.long_(Json.of(2L)));
assertEquals(3L, JsonDecoder.long_(Json.of(new BigInteger("3"))));
assertEquals(4L, JsonDecoder.long_(Json.of(new BigDecimal("4"))));
assertThrows(
JsonDecodeException.class,
() -> JsonDecoder.long_(Json.of(new BigDecimal("43242523525235235255")))
);
assertThrows(
JsonDecodeException.class,
() -> JsonDecoder.long_(Json.of("abc"))
);
}

@Test
public void floatDecoderTest() {
assertEquals(1f, JsonDecoder.float_(Json.of(1)));
assertEquals(2f, JsonDecoder.float_(Json.of(2L)));
assertEquals(3f, JsonDecoder.float_(Json.of(new BigInteger("3"))));
assertEquals(4f, JsonDecoder.float_(Json.of(new BigDecimal("4"))));
assertThrows(
JsonDecodeException.class,
() -> JsonDecoder.long_(Json.of("abc"))
);
}

@Test
public void doubleDecoderTest() {
assertEquals(1L, JsonDecoder.double_(Json.of(1)));
assertEquals(2L, JsonDecoder.double_(Json.of(2L)));
assertEquals(3L, JsonDecoder.double_(Json.of(new BigInteger("3"))));
assertEquals(4L, JsonDecoder.double_(Json.of(new BigDecimal("4"))));
assertThrows(
JsonDecodeException.class,
() -> JsonDecoder.double_(Json.of("abc"))
);
}

@Test
public void nullDecoderTest() {
assertNull(JsonDecoder.null_(JsonNull.instance()));
assertEquals(5, JsonDecoder.null_(JsonNull.instance(), 5));
assertThrows(
JsonDecodeException.class,
() -> JsonDecoder.null_(Json.of("abc"))
);
}
}
15 changes: 15 additions & 0 deletions src/test/java/dev/mccue/json/JsonTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,19 @@ public void testOfNumbers() {
public void testOfString() {
assertEquals(Json.of("abc"), JsonString.of("abc"));
}

@Test
public void testTrueRepr() {
assertEquals("true", JsonTrue.instance().toString());
}

@Test
public void testFalseRepr() {
assertEquals("false", JsonFalse.instance().toString());
}

@Test
public void testNullRepr() {
assertEquals("null", JsonNull.instance().toString());
}
}
115 changes: 114 additions & 1 deletion src/test/java/dev/mccue/json/SerializationTest.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package dev.mccue.json;

import dev.mccue.json.serialization.JsonSerializationProxy;
import org.junit.jupiter.api.Test;

import java.io.*;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.*;

public class SerializationTest {
@Test
Expand All @@ -32,4 +35,114 @@ public void testSerialization() throws IOException, ClassNotFoundException {
assertEquals(json, ois.readObject());
}
}

@Test
public void testNonsenseForm() throws IOException, ClassNotFoundException {
byte[] data;
try (var baos = new ByteArrayOutputStream();
var oos = new ObjectOutputStream(baos)) {
oos.writeObject(new JsonSerializationProxy(""));
oos.writeObject(new JsonSerializationProxy("{\"a\":"));
data = baos.toByteArray();
}

try (var bais = new ByteArrayInputStream(data);
var ois = new ObjectInputStream(bais)) {
assertThrows(JsonReadException.class, ois::readObject);
assertThrows(JsonReadException.class, ois::readObject);
}
}

@Test
public void testMalicousStream() throws IOException, ClassNotFoundException {
byte[] jsonNull = {
-84, -19, 0, 5, 115, 114, 0, 23, 100, 101, 118, 46, 109, 99, 99, 117, 101, 46, 106, 115, 111, 110, 46, 74, 115, 111, 110, 78, 117, 108, 108, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 120, 112
};

byte[] jsonTrue = {
-84, -19, 0, 5, 115, 114, 0, 23, 100, 101, 118, 46, 109, 99, 99, 117, 101, 46, 106, 115, 111, 110, 46, 74, 115, 111, 110, 84, 114, 117, 101, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 120, 112
};

byte[] jsonFalse = {
-84, -19, 0, 5, 115, 114, 0, 24, 100, 101, 118, 46, 109, 99, 99, 117, 101, 46, 106, 115, 111, 110, 46, 74, 115, 111, 110, 70, 97, 108, 115, 101, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 120, 112
};

/*byte[] data;
try (var baos = new ByteArrayOutputStream();
var oos = new ObjectOutputStream(baos)) {
oos.writeObject(JsonFalse.instance());
data = baos.toByteArray();
}
System.out.println(Arrays.toString(data));*/


try (var ois = new ObjectInputStream(new ByteArrayInputStream(jsonNull))) {
assertThrows(IllegalStateException.class, ois::readObject);
}

try (var ois = new ObjectInputStream(new ByteArrayInputStream(jsonTrue))) {
assertThrows(IllegalStateException.class, ois::readObject);
}

try (var ois = new ObjectInputStream(new ByteArrayInputStream(jsonFalse))) {
assertThrows(IllegalStateException.class, ois::readObject);
}
}

private Object roundTrip(Object o) throws IOException, ClassNotFoundException {
byte[] data;
try (var baos = new ByteArrayOutputStream();
var oos = new ObjectOutputStream(baos)) {
oos.writeObject(o);
data = baos.toByteArray();
}

try (var bais = new ByteArrayInputStream(data);
var ois = new ObjectInputStream(bais)) {
return ois.readObject();
}
}

@Test
public void roundTripTrue() throws IOException, ClassNotFoundException {
assertEquals(JsonTrue.instance(), roundTrip(JsonTrue.instance()));
assertSame(JsonTrue.instance(), roundTrip(JsonTrue.instance()));
}

@Test
public void roundTripFalse() throws IOException, ClassNotFoundException {
assertEquals(JsonFalse.instance(), roundTrip(JsonFalse.instance()));
assertSame(JsonFalse.instance(), roundTrip(JsonFalse.instance()));
}

@Test
public void roundTripNull() throws IOException, ClassNotFoundException {
assertEquals(JsonNull.instance(), roundTrip(JsonNull.instance()));
assertSame(JsonNull.instance(), roundTrip(JsonNull.instance()));
}

@Test
public void roundTripString() throws IOException, ClassNotFoundException {
assertEquals(JsonString.of("abc"), roundTrip(JsonString.of("abc")));
}

@Test
public void roundTripArray() throws IOException, ClassNotFoundException {
var o = JsonArray.of(
JsonString.of("abc"),
JsonNull.instance()
);
assertEquals(o, roundTrip(o));
}

@Test
public void roundTripObject() throws IOException, ClassNotFoundException {
var o = JsonObject.of(Map.of(
"abc", JsonString.of("def"),
"ghi", JsonNull.instance(),
"kjl", JsonArray.of()
));
assertEquals(o, roundTrip(o));
}
}

0 comments on commit d856332

Please sign in to comment.