diff options
-rw-r--r-- | container-search/src/main/java/com/yahoo/search/rendering/JsonRenderer.java | 37 | ||||
-rw-r--r-- | container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java | 48 |
2 files changed, 81 insertions, 4 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/rendering/JsonRenderer.java b/container-search/src/main/java/com/yahoo/search/rendering/JsonRenderer.java index 55c846ccb5b..7d60d7cf9ee 100644 --- a/container-search/src/main/java/com/yahoo/search/rendering/JsonRenderer.java +++ b/container-search/src/main/java/com/yahoo/search/rendering/JsonRenderer.java @@ -9,7 +9,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Preconditions; import com.yahoo.data.JsonProducer; import com.yahoo.data.access.Inspectable; +import com.yahoo.data.access.Inspector; +import com.yahoo.data.access.Type; import com.yahoo.data.access.simple.JsonRender; +import com.yahoo.data.access.simple.Value; import com.yahoo.document.datatypes.FieldValue; import com.yahoo.document.datatypes.StringFieldValue; import com.yahoo.document.datatypes.TensorFieldValue; @@ -741,6 +744,34 @@ public class JsonRenderer extends AsynchronousSectionedRenderer<Result> { return true; } + private static Inspector wrapAsMap(Inspector data) { + if (data.type() != Type.ARRAY) return null; + if (data.entryCount() == 0) return null; + Value.ObjectValue map = new Value.ObjectValue(); + for (int i = 0; i < data.entryCount(); i++) { + Inspector obj = data.entry(i); + if (obj.type() != Type.OBJECT) return null; + if (obj.fieldCount() != 2) return null; + Inspector key = obj.field("key"); + Inspector value = obj.field("value"); + if (key.type() != Type.STRING) return null; + if (! value.valid()) return null; + map.put(key.asString(), value); + } + return map; + } + + private void renderInspector(Inspector data) throws IOException { + StringBuilder intermediate = new StringBuilder(); + Inspector asMap = wrapAsMap(data); + if (asMap != null) { + JsonRender.render(asMap, intermediate, true); + } else { + JsonRender.render(data, intermediate, true); + } + generator.writeRawValue(intermediate.toString()); + } + private void renderFieldContents(Object field) throws IOException { if (field == null) { generator.writeNull(); @@ -750,12 +781,10 @@ public class JsonRenderer extends AsynchronousSectionedRenderer<Result> { generator.writeTree((TreeNode) field); } else if (field instanceof Tensor) { renderTensor(Optional.of((Tensor)field)); + } else if (field instanceof Inspectable) { + renderInspector(((Inspectable)field).inspect()); } else if (field instanceof JsonProducer) { generator.writeRawValue(((JsonProducer) field).toJson()); - } else if (field instanceof Inspectable) { - StringBuilder intermediate = new StringBuilder(); - JsonRender.render((Inspectable) field, intermediate, true); - generator.writeRawValue(intermediate.toString()); } else if (field instanceof StringFieldValue) { generator.writeString(((StringFieldValue)field).getString()); } else if (field instanceof TensorFieldValue) { diff --git a/container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java b/container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java index bf56ad19f44..caad1c76362 100644 --- a/container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/rendering/JsonRendererTestCase.java @@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.ListenableFuture; import com.yahoo.component.chain.Chain; +import com.yahoo.data.access.simple.Value; import com.yahoo.data.access.slime.SlimeAdapter; import com.yahoo.document.DataType; import com.yahoo.document.DocumentId; @@ -1111,6 +1112,53 @@ public class JsonRendererTestCase { } @Test + public final void testMapInField() throws IOException, InterruptedException, ExecutionException, JSONException { + String expected = "{\n" + + " \"root\": {\n" + + " \"children\": [\n" + + " {\n" + + " \"fields\": {\n" + + " \"structured\": {\n" + + " \"foo\": \"string foo\",\n" + + " \"bar\": [\"array bar elem 1\", \"array bar elem 2\"],\n" + + " \"baz\": {\"f1\": \"object baz field 1\", \"f2\": \"object baz field 2\"}\n" + + " }\n" + + " },\n" + + " \"id\": \"MapInField\",\n" + + " \"relevance\": 1.0\n" + + " }\n" + + " ],\n" + + " \"fields\": {\n" + + " \"totalCount\": 1\n" + + " },\n" + + " \"id\": \"toplevel\",\n" + + " \"relevance\": 1.0\n" + + " }\n" + + "}\n"; + Result r = newEmptyResult(); + Hit h = new Hit("MapInField"); + Value.ArrayValue atop = new Value.ArrayValue(); + atop.add(new Value.ObjectValue() + .put("key", new Value.StringValue("foo")) + .put("value", new Value.StringValue("string foo"))) + .add(new Value.ObjectValue() + .put("key", new Value.StringValue("bar")) + .put("value", new Value.ArrayValue() + .add(new Value.StringValue("array bar elem 1")) + .add(new Value.StringValue("array bar elem 2")))) + .add(new Value.ObjectValue() + .put("key", new Value.StringValue("baz")) + .put("value", new Value.ObjectValue() + .put("f1", new Value.StringValue("object baz field 1")) + .put("f2", new Value.StringValue("object baz field 2")))); + h.setField("structured", atop); + r.hits().add(h); + r.setTotalHitCount(1L); + String summary = render(r); + assertEqualJson(expected, summary); + } + + @Test public void testThatTheJsonValidatorCanCatchErrors() { String json = "{" + " \"root\": {" |