Author: npeltier Date: Wed Sep 20 20:46:35 2017 New Revision: 1809079 URL: http://svn.apache.org/viewvc?rev=1809079&view=rev Log: SLING-7117 add JsonPath configuration
not full json path support even though it could be interesting, as it would need an external library Modified: sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/internal/JsonPipe.java sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/internal/JsonPipeTest.java Modified: sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/internal/JsonPipe.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/internal/JsonPipe.java?rev=1809079&r1=1809078&r2=1809079&view=diff ============================================================================== --- sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/internal/JsonPipe.java (original) +++ sling/trunk/contrib/extensions/sling-pipes/src/main/java/org/apache/sling/pipes/internal/JsonPipe.java Wed Sep 20 20:46:35 2017 @@ -16,16 +16,6 @@ */ package org.apache.sling.pipes.internal; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.Iterator; - -import javax.json.JsonArray; -import javax.json.JsonException; -import javax.json.JsonStructure; -import javax.json.JsonValue.ValueType; - import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.sling.api.resource.Resource; @@ -34,12 +24,38 @@ import org.apache.sling.pipes.Plumber; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.json.JsonArray; +import javax.json.JsonArrayBuilder; +import javax.json.JsonException; +import javax.json.JsonObject; +import javax.json.JsonStructure; +import javax.json.JsonValue.ValueType; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Iterator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * Pipe outputting binding related to a json stream: either an object */ public class JsonPipe extends AbstractInputStreamPipe { private static Logger logger = LoggerFactory.getLogger(JsonPipe.class); - public static final String RESOURCE_TYPE = RT_PREFIX + "json"; + public final static String RESOURCE_TYPE = RT_PREFIX + "json"; + + /** + * property specifying the json path where to fetched the used value + */ + protected static final String PN_VALUEPATH = "valuePath"; + + protected static final String JSONPATH_ROOT = "$"; + + protected static final String ARRAY_START = "["; + + protected static final String OBJ_START = "."; + + protected static final Pattern JSONPATH_FIRSTTOKEN = Pattern.compile("^\\" + JSONPATH_ROOT + "([\\" + OBJ_START + "\\" + ARRAY_START + "])([^\\" + OBJ_START + "\\]\\" + ARRAY_START + "]+)\\]?"); JsonArray array; int index = -1; @@ -63,35 +79,42 @@ public class JsonPipe extends AbstractIn JsonStructure json; try { json = JsonUtil.parse(jsonString); + } catch (JsonException ex) { json = null; } if (json == null) { binding = jsonString.trim(); output = inputSingletonIterator; - } else if (json.getValueType() != ValueType.ARRAY) { - binding = JsonUtil.unbox(json); - output = inputSingletonIterator; } else { - binding = array = (JsonArray) json; - index = 0; - output = new Iterator<Resource>() { - @Override - public boolean hasNext() { - return index < array.size(); - } - - @Override - public Resource next() { - try { - binding = JsonUtil.unbox(array.get(index)); - } catch (Exception e) { - logger.error("Unable to retrieve {}nth item of jsonarray", index, e); + String valuePath = properties.get(PN_VALUEPATH, String.class); + if (StringUtils.isNotBlank(valuePath)){ + json = getValue(json, valuePath); + } + if (json.getValueType() != ValueType.ARRAY) { + binding = JsonUtil.unbox(json); + output = inputSingletonIterator; + } else { + binding = array = (JsonArray) json; + index = 0; + output = new Iterator<Resource>() { + @Override + public boolean hasNext() { + return index < array.size(); } - index++; - return getInput(); - } - }; + + @Override + public Resource next() { + try { + binding = JsonUtil.unbox(array.get(index)); + } catch (Exception e) { + logger.error("Unable to retrieve {}nth item of jsonarray", index, e); + } + index++; + return getInput(); + } + }; + } } } }catch (Exception e) { @@ -99,4 +122,34 @@ public class JsonPipe extends AbstractIn } return output; } + + /** + * Returns fetched json value from value path + * @param json json structure from which to start + * @param valuePath path to follow + * @return value fetched after following the path + */ + protected JsonStructure getValue(JsonStructure json, String valuePath){ + Matcher matcher = JSONPATH_FIRSTTOKEN.matcher(valuePath); + if (matcher.find()){ + String firstChar = matcher.group(1); + String content = matcher.group(2); + logger.trace("first char is {}, content is {}", firstChar, content); + if (ARRAY_START.equals(firstChar)){ + JsonArray array = (JsonArray)json; + int index = Integer.parseInt(content); + json = (JsonStructure)array.get(index); + } else if (OBJ_START.equals(firstChar)){ + JsonObject object = (JsonObject)json; + json = (JsonStructure)object.get(content); + } + valuePath = StringUtils.removeStart(valuePath, matcher.group(0)); + if (StringUtils.isNotBlank(valuePath)){ + valuePath = JSONPATH_ROOT + valuePath; + return getValue(json, valuePath); + } + } + return json; + } + } Modified: sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/internal/JsonPipeTest.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/internal/JsonPipeTest.java?rev=1809079&r1=1809078&r2=1809079&view=diff ============================================================================== --- sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/internal/JsonPipeTest.java (original) +++ sling/trunk/contrib/extensions/sling-pipes/src/test/java/org/apache/sling/pipes/internal/JsonPipeTest.java Wed Sep 20 20:46:35 2017 @@ -22,14 +22,15 @@ import static org.junit.Assert.assertTru import java.util.Iterator; -import org.apache.sling.api.resource.PersistenceException; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.pipes.AbstractPipeTest; -import org.apache.sling.pipes.Pipe; +import org.apache.sling.pipes.PipeBuilder; import org.junit.Before; import org.junit.Test; +import javax.json.JsonObject; + /** * testing json pipe with anonymous yahoo meteo API */ @@ -71,4 +72,23 @@ public class JsonPipeTest extends Abstra public void testPipedArray() throws Exception { testArray(getOutput(ARRAY)); } + + @Test + public void testSimpleJsonPath() throws Exception { + testJsonPath("{'size':2, 'items':[{'test':'one'}, {'test':'two'}]}", "$.items"); + testJsonPath("[['foo','bar'],[{'test':'one'}, {'test':'two'}]]", "$[1]"); + } + @Test + public void testNestedJsonPath() throws Exception { + testJsonPath("{'arrays':[['foo','bar'],[{'test':'one'}, {'test':'two'}]]}", "$.arrays[1]"); + testJsonPath("{'objects':{'items':[{'test':'one'}, {'test':'two'}]}}", "$.objects.items"); + } + + protected void testJsonPath(String json, String valuePath) throws Exception { + assertEquals("there should be 2 results for valuePath " + valuePath, 2, plumber.newPipe(context.resourceResolver()) + .echo("/content/fruits") + .json(json).with("valuePath", valuePath).name("json") + .echo("/content/json/array/${json.test}") + .run().size()); + } } \ No newline at end of file