Skip to content

Commit

Permalink
Merge pull request #47 from bowbahdoe/cleanup-march-1
Browse files Browse the repository at this point in the history
Add json Encoder and bump version
  • Loading branch information
bowbahdoe authored Mar 2, 2023
2 parents d856332 + 7e1f0a3 commit 27b968f
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 3 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ Requires Java 17+.
<dependency>
<groupId>dev.mccue</groupId>
<artifactId>json</artifactId>
<version>0.2.2</version>
<version>0.2.3</version>
</dependency>
```

### Gradle

```
dependencies {
implementation("dev.mccue:json:0.2.2")
implementation("dev.mccue:json:0.2.3")
}
```

Expand Down
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.2</version>
<version>0.2.3</version>
<packaging>jar</packaging>

<properties>
Expand Down
65 changes: 65 additions & 0 deletions src/main/java/dev/mccue/json/Json.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,41 @@ static Json of(Collection<? extends JsonEncodable> value) {
);
}

/**
* Creates {@link Json} from a {@link Collection} of items which
* can be encoded with a provided {@link JsonEncoder}.
*
* @param value The value to be encoded.
* @return An instance of {@link Json}.
*/
static <T> Json of(Collection<? extends T> value, JsonEncoder<T> encoder) {
return value == null
? JsonNull.instance()
: new ArrayImpl(
value.stream()
.map(v -> {
var result = encoder.encode(v);
if (result == null) {
return JsonNull.instance();
}
else {
return result;
}
})
.toList()
);
}


/**
* Creates {@link Json} from a {@link Map} with {@link String} keys to values which
* implement {@link JsonEncodable}.
*
* <p>
* Note that this method is null-safe when provided a null container,
* but only null-safe for map values if the provided encoder also is.
* </p>
*
* @param value The value to be encoded.
* @return An instance of {@link Json}.
*/
Expand All @@ -262,6 +293,40 @@ static Json of(Map<String, ? extends JsonEncodable> value) {
);
}

/**
* Creates {@link Json} from a {@link Map} with {@link String} keys to values which
* can be encoded with a provided {@link JsonEncoder}.
*
* <p>
* Note that this method is null-safe when provided a null container,
* but only null-safe for map values if the provided encoder also is.
* </p>
*
* @param value The value to be encoded.
* @return An instance of {@link Json}.
*/
static <T> Json of(Map<String, ? extends T> value, JsonEncoder<T> encoder) {
return value == null
? JsonNull.instance()
: new ObjectImpl(
value
.entrySet()
.stream()
.collect(Collectors.toUnmodifiableMap(
Map.Entry::getKey,
entry -> {
var result = encoder.encode(entry.getValue());
if (result == null) {
return JsonNull.instance();
}
else {
return result;
}
}
))
);
}

/**
* Creates a new {@link JsonObject.Builder}.
*
Expand Down
54 changes: 54 additions & 0 deletions src/main/java/dev/mccue/json/JsonEncoder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package dev.mccue.json;

import java.util.function.Function;

/**
* Object that knows how to encode an object into Json.
*
* <p>
* This is a counterpart to {@link JsonEncodable} which can be provided
* to encode objects in contexts where elements are not, for whatever reason,
* have an intrinsic Json representation.
* </p>
* @param <T> The type of element to encode.
*/
public interface JsonEncoder<T> {
/**
* Encodes the given value to Json.
* @param value The value to encode.
* @return The encoded value.
*/
Json encode(T value);


/**
* Creates a {@link JsonEncoder} which delegates to an intrinsic implementation
* provided by virtue of being {@link JsonEncodable}.
* @return A {@link JsonEncoder}.
* @param <T> The type to encode.
*/
static <T extends JsonEncodable> JsonEncoder<T> of() {
return JsonEncodable::toJson;
}

/**
* Convenience method to target a lambda expression to a {@link JsonEncoder}
* and be able to call methods such as {@link JsonEncoder#map(Function)}.
* @param encoder The expression to wrap as an encoder.
* @return A {@link JsonEncoder}.
* @param <T> The type to encode.
*/
static <T> JsonEncoder<T> of(JsonEncoder<? super T> encoder) {
return encoder::encode;
}

/**
* Maps the result of this encoder.
* @param f The function to apply.
* @return An encoder that encodes a different type.
* @param <R> The type the returned encoder will encode.
*/
default <R> JsonEncoder<R> map(Function<? super R, ? extends T> f) {
return r -> this.encode(f.apply(r));
}
}
60 changes: 60 additions & 0 deletions src/test/java/dev/mccue/json/JsonTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

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

Expand Down Expand Up @@ -34,6 +36,64 @@ public void testOfCollection() {
JsonArray.of(Json.ofFalse(), Json.of(1), Json.of("abc")),
Json.of(List.of((JsonEncodable) Json::ofFalse, Json.of(1), Json.of("abc")))
);

var l = new ArrayList<Json>();
l.add(null);
assertEquals(
JsonArray.of(JsonNull.instance()),
Json.of(l)
);
}

@Test
public void testOfCollectionEncodable() {
assertEquals(
JsonArray.of(Json.ofFalse()),
Json.of(List.of(false), JsonBoolean::of)
);

assertEquals(
JsonArray.of(Json.ofNull()),
Json.of(List.of(false), __ -> null)
);

assertEquals(
JsonArray.of(Json.ofNull()),
Json.of(List.of(false), __ -> JsonNull.instance())
);
}

@Test
public void testOfMap() {
var m = new HashMap<String, JsonEncodable>();
m.put("a", null);
m.put("b", Json.of(1));

assertEquals(
JsonObject.of(Map.of(
"a", JsonNull.instance(),
"b", Json.of(1)
)),
Json.of(m)
);
}

@Test
public void testOfMapEncoder() {
var m = new HashMap<String, Integer>();
m.put("a", 6);
m.put("b", 7);

m.put("c", null);

assertEquals(
JsonObject.of(Map.of(
"a", Json.of(6),
"b", Json.of(7),
"c", JsonNull.instance()
)),
Json.of(m, Json::of)
);
}

@Test
Expand Down

0 comments on commit 27b968f

Please sign in to comment.