Skip to content

Commit

Permalink
[json-node] Add JsonNodeMapper.properties() method (#321)
Browse files Browse the repository at this point in the history
* [json-node] Add JsonNodeMapper.properties() method

Match the feature of SimpleMapper and Jsonb.

* [json-node] Reorder methods on SimpleMapper JsonNodeMapper

* Test only - CustomAdapterTest to use JsonStream in builder
  • Loading branch information
rbygrave authored Dec 16, 2024
1 parent fef89cf commit fda6924
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 32 deletions.
36 changes: 18 additions & 18 deletions json-core/src/main/java/io/avaje/json/simple/SimpleMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,7 @@ static Builder builder() {
}

/**
* Return the property names as PropertyNames.
* <p>
* Provides the option of optimising the writing of json for property names
* by having them already escaped and encoded rather than as plain strings.
*/
PropertyNames properties(String... names);

/**
* Return a mapper for Object with more reading/writing options.
* Return a mapper for any json content.
*/
Type<Object> object();

Expand All @@ -66,15 +58,6 @@ static Builder builder() {
*/
Type<List<Object>> list();

/**
* Return a Type specific mapper for the given JsonAdapter.
*
* @param customAdapter The custom adapter to use.
* @param <T> The type of the class to map to/from json.
* @return The Type specific mapper.
*/
<T> Type<T> type(JsonAdapter<T> customAdapter);

/**
* Write the object to JSON string.
* <p>
Expand Down Expand Up @@ -109,6 +92,23 @@ static Builder builder() {
*/
List<Object> fromJsonArray(String json);

/**
* Return the property names as PropertyNames.
* <p>
* Provides the option of optimising the writing of json for property names
* by having them already escaped and encoded rather than as plain strings.
*/
PropertyNames properties(String... names);

/**
* Return a Type specific mapper for the given JsonAdapter.
*
* @param customAdapter The custom adapter to use.
* @param <T> The type of the class to map to/from json.
* @return The Type specific mapper.
*/
<T> Type<T> type(JsonAdapter<T> customAdapter);

/**
* Build the JsonNodeMapper.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.avaje.json.JsonAdapter;
import io.avaje.json.JsonReader;
import io.avaje.json.JsonWriter;
import io.avaje.json.stream.JsonStream;
import org.junit.jupiter.api.Test;

import java.util.List;
Expand All @@ -13,7 +14,8 @@

class CustomAdapterTest {

static final SimpleMapper simpleMapper = SimpleMapper.builder().build();
static final JsonStream jsonStream = JsonStream.builder().build();
static final SimpleMapper simpleMapper = SimpleMapper.builder().jsonStream(jsonStream).build();
static final MyAdapter myAdapter = new MyAdapter(simpleMapper);
static final SimpleMapper.Type<MyCustomType> type = simpleMapper.type(myAdapter);

Expand Down
31 changes: 20 additions & 11 deletions json-node/src/main/java/io/avaje/json/node/JsonNodeMapper.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.avaje.json.node;

import io.avaje.json.JsonAdapter;
import io.avaje.json.PropertyNames;
import io.avaje.json.node.adapter.NodeAdapterBuilder;
import io.avaje.json.simple.SimpleMapper;
import io.avaje.json.stream.JsonStream;
Expand All @@ -19,8 +20,8 @@
* static final JsonNodeMapper mapper = JsonNodeMapper.builder().build();
*
* JsonArray jsonArray = JsonArray.create()
* .add(JsonInteger.of(42))
* .add(JsonString.of("foo"));
* .add(42)
* .add("foo");
*
* var asJson = mapper.toJson(jsonArray);
*
Expand All @@ -41,15 +42,6 @@ static Builder builder() {
return new NodeAdapterBuilder();
}

/**
* Create a NodeMapper for the specific type given the JsonAdapter.
*
* @param customAdapter The type specific JsonAdapter to use.
* @param <T> The specific custom type being mapped.
* @return The type specific NodeMapper.
*/
<T> SimpleMapper.Type<T> mapper(JsonAdapter<T> customAdapter);

/**
* Return a NodeMapper for ANY json content.
* <p>
Expand Down Expand Up @@ -157,6 +149,23 @@ static Builder builder() {
*/
JsonAdapter<?> adapter(Type type);

/**
* Return the property names as PropertyNames.
* <p>
* Provides the option of optimising the writing of json for property names
* by having them already escaped and encoded rather than as plain strings.
*/
PropertyNames properties(String... names);

/**
* Return a Type specific mapper for the given JsonAdapter.
*
* @param customAdapter The custom adapter to use.
* @param <T> The type of the class to map to/from json.
* @return The Type specific mapper.
*/
<T> SimpleMapper.Type<T> type(JsonAdapter<T> customAdapter);

/**
* Build the JsonNodeMapper.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.avaje.json.JsonAdapter;
import io.avaje.json.JsonReader;
import io.avaje.json.PropertyNames;
import io.avaje.json.node.*;
import io.avaje.json.simple.SimpleMapper;
import io.avaje.json.stream.JsonStream;
Expand Down Expand Up @@ -31,7 +32,12 @@ final class DJsonNodeMapper implements JsonNodeMapper {
}

@Override
public <T> SimpleMapper.Type<T> mapper(JsonAdapter<T> customAdapter) {
public PropertyNames properties(String... names) {
return jsonStream.properties(names);
}

@Override
public <T> SimpleMapper.Type<T> type(JsonAdapter<T> customAdapter) {
return new DMapper<>(customAdapter, jsonStream);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.avaje.json.JsonAdapter;
import io.avaje.json.JsonReader;
import io.avaje.json.JsonWriter;
import io.avaje.json.PropertyNames;
import io.avaje.json.simple.SimpleMapper;
import org.junit.jupiter.api.Test;

Expand All @@ -16,7 +17,21 @@ class CustomAdapterTest {

static final JsonNodeMapper mapper = JsonNodeMapper.builder().build();
static final MyAdapter myAdapter = new MyAdapter(mapper);
static final SimpleMapper.Type<MyCustomType> typeMapper = mapper.mapper(myAdapter);
static final SimpleMapper.Type<MyCustomType> typeMapper = mapper.type(myAdapter);

@Test
void propertyNames() {

var adapter = new MyAdapter2(mapper);
SimpleMapper.Type<MyCustomType> type = mapper.type(adapter);

var source = as("a", 1);
String asJson = type.toJson(source);
assertThat(asJson).isEqualTo("{\"foo\":\"a\",\"bar\":1}");

MyCustomType myCustomType = type.fromJson(asJson);
assertThat(myCustomType).isEqualTo(source);
}

@Test
void mapUsingCustomAdapter() {
Expand Down Expand Up @@ -110,4 +125,48 @@ public MyCustomType fromJson(JsonReader reader) {
return myCustomType;
}
}

static class MyAdapter2 implements JsonAdapter<MyCustomType> {

final SimpleMapper.Type<JsonObject> objectMapper;
final PropertyNames names;

public MyAdapter2(JsonNodeMapper mapper) {
this.objectMapper = mapper.objectMapper();
this.names = mapper.properties("foo", "bar");
}

@Override
public void toJson(JsonWriter writer, MyCustomType value) {
writer.beginObject(names);
writer.name(0);
writer.value(value.foo);
writer.name(1);
writer.value(value.bar);
writer.endObject();
}

@Override
public MyCustomType fromJson(JsonReader reader) {
MyCustomType myCustomType = new MyCustomType();
reader.beginObject(names);

String name;
while (reader.hasNextField()) {
name = reader.nextField();
switch (name) {
case "foo":
myCustomType.foo = reader.readString();
break;
case "bar":
myCustomType.bar = reader.readInt();
break;
default:
reader.unmappedField(name);
reader.skipValue();
}
}
return myCustomType;
}
}
}

0 comments on commit fda6924

Please sign in to comment.