Skip to content

Commit

Permalink
Fix #66 (add Json.mapOfFrom())
Browse files Browse the repository at this point in the history
  • Loading branch information
Tatu Saloranta committed Sep 9, 2019
1 parent 9526e04 commit 73b7691
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 10 deletions.
27 changes: 27 additions & 0 deletions jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/JSON.java
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,33 @@ public Map<String,Object> mapFrom(Object source) throws IOException, JSONObjectE
}
}

/**
* Read method for reading a {@link Map} of {@code type} (usually POJO) values.
*
* @since 2.10
*/
@SuppressWarnings("unchecked")
public <T> Map<String,T> mapOfFrom(Class<T> type, Object source) throws IOException, JSONObjectException
{
if (source instanceof JsonParser) {
JsonParser p = _initForReading((JsonParser) source);
Map<?,?> result = _readerForOperation(p).readMapOf(type);
p.clearCurrentToken();
return (Map<String,T>) result;
}
JsonParser p = _parser(source);
try {
_initForReading(_config(p));
Map<?,?> result = _readerForOperation(p).readMapOf(type);
JsonParser p0 = p;
p = null;
_close(p0, null);
return (Map<String,T>) result;
} catch (Exception e) {
return _closeWithError(p, e);
}
}

public <T> T beanFrom(Class<T> type, Object source) throws IOException, JSONObjectException
{
if (source instanceof JsonParser) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public class ValueIterator<T> implements Iterator<T>, Closeable

/**
* @param managedParser Whether we "own" the {@link JsonParser} passed or not:
* if true, it was created by {@link ObjectReader} and code here needs to
* if true, it was created by {@code Json} and code here needs to
* close it; if false, it was passed by calling code and should not be
* closed by iterator.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,8 @@ public <T> T[] readArrayOf(Class<T> type) throws IOException {

/**
* Method for reading a JSON Array from input and building a {@link java.util.List}
* out of it. Note that if input does NOT contain a
* JSON Array, {@link JSONObjectException} will be thrown.
* out of it, binding values into specified {@code type}.
* Note that if input does NOT contain a JSON Array, {@link JSONObjectException} will be thrown.
*/
@SuppressWarnings("unchecked")
public <T> List<T> readListOf(Class<T> type) throws IOException
Expand All @@ -282,7 +282,29 @@ public <T> List<T> readListOf(Class<T> type) throws IOException
return (List<T>) new CollectionReader(List.class, _readerLocator.findReader(type))
.read(this, _parser);
}


/**
* Method for reading a JSON Object from input and building a {@link java.util.Map}
* out of it, binding values into specified {@code type}.
* Note that if input does NOT contain a JSON Object, {@link JSONObjectException} will be thrown.
*
* @since 2.10
*/
@SuppressWarnings("unchecked")
public <T> Map<String, T> readMapOf(Class<T> type) throws IOException
{
JsonToken t = _parser.getCurrentToken();
if (t == JsonToken.VALUE_NULL) {
return null;
}
if (t != JsonToken.START_OBJECT) {
throw JSONObjectException.from(_parser,
"Can not read a Map: expect to see START_OBJECT ('{'), instead got: "+ValueReader._tokenDesc(_parser));
}
return (Map<String, T>) new MapReader(Map.class, _readerLocator.findReader(type))
.read(this, _parser);
}

/*
/**********************************************************************
/* Internal methods; overridable for custom coercions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ public class POJODefinition
public final Constructor<?> stringCtor;
public final Constructor<?> longCtor;

/**
* Constructors used for serialization use case
*/
public POJODefinition(Class<?> type, Prop[] props,
Constructor<?> defaultCtor0, Constructor<?> stringCtor0, Constructor<?> longCtor0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,13 @@ public ValueReaderLocator perOperationInstance(JSONReader r, int features) {

/**
* Method used during deserialization to find handler for given
* non-generic type.
* non-generic type: will first check for already resolved (and cached) readers
* -- and return if one found -- and then if no cached reader found, create
* one, cache, return.
*
* @param raw Type-erased type of value to find reader for
*
* @return ValueReader to use for given type
*/
public ValueReader findReader(Class<?> raw)
{
Expand All @@ -182,7 +188,12 @@ public ValueReader findReader(Class<?> raw)
}

/**
* Factory method for creating standard readers of any declared type
* Factory method for creating standard readers of any declared type.
*
* @param contextType Context for resolving generic type parameters
* @param type Type-erased type of value to construct reader for
* @param genericType Full (possibly) generic type of value to construct reader for (important
* for {@link java.util.Map}, {@link java.util.Collection}).
*/
protected ValueReader createReader(Class<?> contextType, Class<?> type, Type genericType)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public void testPOJOWithMap() throws Exception
assertEquals(2, map.stuff.size());
assertEquals(Integer.valueOf(4), map.stuff.get("b"));
}

public void testSimpleBeanCollections() throws Exception
{
final String INPUT = aposToQuotes("["
Expand Down Expand Up @@ -153,6 +153,23 @@ public void testSimpleBeanCollections() throws Exception
assertEquals("Bacon", beans2.get(1).name.last);
}

// @since 2.10
public void testSimpleBeanMaps() throws Exception
{
final String INPUT = aposToQuotes("{ 'first':"
+"{'name':{'first':'Bob','last':'Burger'},'x':13}"
+", 'second':{'x':-145,'name':{'first':'Billy','last':'Bacon'}}"
+"}");
Map<String, TestBean> stuff = JSON.std.mapOfFrom(TestBean.class, INPUT);
assertEquals(2, stuff.size());
assertNotNull(stuff.get("first"));
TestBean bean2 = stuff.get("second");
assertNotNull(bean2);
assertEquals(-145, bean2.x);
assertEquals("Billy", bean2.name.first);
assertEquals("Bacon", bean2.name.last);
}

public void testJvmSerializersPOJO() throws Exception
{
MediaItem.Content content = new MediaItem.Content();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,25 @@ public JsonParser treeAsTokens(TreeNode node) {
*/

/**
* Factory method for constructing node to represent Boolean values.
*
* @param state Whether to create {@code Boolean.TRUE} or {@code Boolean.FALSE} node
*
* @return Node instance for given boolean value
*
* @since 2.8
*/
public JrsBoolean booleanNode(boolean state) {
return state? JrsBoolean.TRUE : JrsBoolean.FALSE;
}

/**
* Factory method for constructing node to represent String values.
*
* @param text String value for constructed node to contain
*
* @return Node instance for given text value
*
* @since 2.8
*/
public JrsString stringNode(String text) {
Expand All @@ -135,6 +147,12 @@ public JrsString stringNode(String text) {
}

/**
* Factory method for constructing node to represent String values.
*
* @param nr Numeric value for constructed node to contain
*
* @return Node instance for given numeric value
*
* @since 2.8
*/
public JrsNumber numberNode(Number nr) {
Expand Down
2 changes: 2 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Project: jackson-jr
#60: Add support for reading "root value" streams (linefeed separated/concatenated)
#63: Change default for `JSON.Feature.USE_FIELDS` to `true` (from false) in 2.10
#65: Allow registration of custom readers, writers (to support 3rd party, custom types)
#66: Add `Json.mapOfFrom(Class)` to support binding POJO-valued maps
(suggested by ocind@github)
- Add `JrsNull` node type for `jr-stree` package
- Add JDK9+ `module-info.class` using Moditect
- Update Retrofit2 version (2.0.0 -> 2.5.0)
Expand Down

0 comments on commit 73b7691

Please sign in to comment.