Fixed Jackson serialization bug for matches
Change-Id: Ife5378f70cdccc1b4af2b9abf81a712bf90cc87d
diff --git a/Changes b/Changes
index e9644b4..5732d43 100644
--- a/Changes
+++ b/Changes
@@ -1,4 +1,4 @@
-0.52 2015-06-25
+0.52 2015-06-26
- [bugfix] Fixed payload filtering in FocusSpans (margaretha)
- [workaround] Reintroduced empty collection support,
as Koral still creates them (diewald)
@@ -15,6 +15,8 @@
- [workaround] Support matches starting with "contains"
(Kustvakt bug/diewald)
- [bugfix] Fixed treatment of several collection types (diewald)
+ - [bugfix] Remove legacy error handling in Match (diewald)
+ - [bugfix] JSON-serialization bug in match in case of error messages (diewald)
0.51 2015-03-17
- This is a major version (prepared for the GitHub release)
diff --git a/Errorcodes b/Errorcodes
index d62c3ae..bb412dd 100644
--- a/Errorcodes
+++ b/Errorcodes
@@ -79,4 +79,5 @@
* 900 - 999 - Corpus Data errors
952: "Given offset information is not numeric"
-953: "Given offset information is incomplete"
\ No newline at end of file
+953: "Given offset information is incomplete"
+970: "Invalid foundry requested"
\ No newline at end of file
diff --git a/src/main/java/de/ids_mannheim/korap/KrillCollection.java b/src/main/java/de/ids_mannheim/korap/KrillCollection.java
index 85a82f1..6fe28c9 100644
--- a/src/main/java/de/ids_mannheim/korap/KrillCollection.java
+++ b/src/main/java/de/ids_mannheim/korap/KrillCollection.java
@@ -237,7 +237,7 @@
}
else {
// TODO!
- throw new QueryException(0,"Unknown match type");
+ throw new QueryException(0, "Unknown match type");
};
return bfilter;
@@ -249,24 +249,20 @@
match = json.get("match").asText();
if (match.equals("match:eq")) {
- return bfilter.and(
- key,
- new RegexFilter(json.get("value").asText())
- );
+ return bfilter.and(key, new RegexFilter(json.get("value")
+ .asText()));
}
else if (match.equals("match:ne")) {
- return bfilter.andNot(
- key,
- new RegexFilter(json.get("value").asText())
- );
+ return bfilter.andNot(key, new RegexFilter(json
+ .get("value").asText()));
};
// TODO! for excludes and contains
- throw new QueryException(0,"Unknown document type");
+ throw new QueryException(0, "Unknown document type");
};
// TODO!
- throw new QueryException(0,"Unknown document operation");
+ throw new QueryException(0, "Unknown document operation");
}
// nested group
diff --git a/src/main/java/de/ids_mannheim/korap/KrillIndex.java b/src/main/java/de/ids_mannheim/korap/KrillIndex.java
index b0120e7..c10e9b9 100644
--- a/src/main/java/de/ids_mannheim/korap/KrillIndex.java
+++ b/src/main/java/de/ids_mannheim/korap/KrillIndex.java
@@ -816,17 +816,17 @@
// Create a filter based on the corpusID and the docID
BooleanQuery bool = new BooleanQuery();
if (match.getTextSigle() != null) {
- bool.add(new TermQuery(
- new Term("textSigle", match.getTextSigle())
- ), BooleanClause.Occur.MUST);
+ bool.add(
+ new TermQuery(new Term("textSigle", match.getTextSigle())),
+ BooleanClause.Occur.MUST);
}
// LEGACY
else {
bool.add(new TermQuery(new Term("ID", match.getDocID())),
- BooleanClause.Occur.MUST);
+ BooleanClause.Occur.MUST);
bool.add(new TermQuery(new Term("corpusID", match.getCorpusID())),
- BooleanClause.Occur.MUST);
+ BooleanClause.Occur.MUST);
};
Filter filter = (Filter) new QueryWrapperFilter(bool);
@@ -849,22 +849,18 @@
if (includeSpans)
regex.append("((\">\"|\"<\"\">\")\":\")?");
-System.err.println("1 >>>>>>> " + regex);
-
// There is a foundry given
if (foundry != null && foundry.size() > 0) {
// Filter out bad foundries
for (i = foundry.size() - 1; i >= 0; i--) {
if (!harmlessFoundry.matcher(foundry.get(i)).matches()) {
- throw new QueryException("Invalid foundry requested: '"
- + foundry.get(i) + "'");
- // foundry.remove(i);
+ match.addError(970, "Invalid foundry requested",
+ foundry.get(i));
+ return match;
};
};
-System.err.println("2 >>>>>>> " + regex);
-
// Build regex for multiple foundries
if (foundry.size() > 0) {
regex.append("(");
@@ -888,8 +884,6 @@
};
};
-System.err.println("3 >>>>>>> " + regex);
-
// Build regex for multiple layers
if (layer.size() > 0) {
regex.append("(");
@@ -914,21 +908,15 @@
};
regex.append("(.){1,}|_[0-9]+");
-System.err.println("5 >>>>>>> " + regex);
-
if (DEBUG)
log.trace("The final regexString is {}", regex.toString());
-System.err.println("6 >>>>>>> " + regex.toString());
-
RegExp regexObj = new RegExp(regex.toString(), RegExp.COMPLEMENT);
fst = new CompiledAutomaton(regexObj.toAutomaton());
if (DEBUG)
log.trace("The final regexObj is {}", regexObj.toString());
};
- System.err.println("++++++++++++++++++++++++++++++++++++++++++");
-
try {
// Iterate over all atomic indices and find the matching document
for (AtomicReaderContext atomic : this.reader().leaves()) {
@@ -1082,8 +1070,8 @@
};
}
catch (IOException e) {
+ match.addError(600, "Unable to read index", e.getLocalizedMessage());
log.warn(e.getLocalizedMessage());
- match.setError(e.getLocalizedMessage());
};
return match;
diff --git a/src/main/java/de/ids_mannheim/korap/index/AbstractDocument.java b/src/main/java/de/ids_mannheim/korap/index/AbstractDocument.java
index 234dded..d1f3efb 100644
--- a/src/main/java/de/ids_mannheim/korap/index/AbstractDocument.java
+++ b/src/main/java/de/ids_mannheim/korap/index/AbstractDocument.java
@@ -6,8 +6,12 @@
import de.ids_mannheim.korap.index.FieldDocument;
import de.ids_mannheim.korap.response.Response;
-import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
/*
* Todo:: Author and textClass may be arrays!
@@ -24,8 +28,11 @@
*
* @author diewald
*/
+@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class AbstractDocument extends Response {
+ ObjectMapper mapper = new ObjectMapper();
+
private String primaryData;
@JsonIgnore
@@ -1050,4 +1057,17 @@
public void setID (String ID) {
this.ID = ID;
};
+
+
+ /**
+ * Serialize response as a {@link JsonNode}.
+ *
+ * @return {@link JsonNode} representation of the response
+ */
+ @Override
+ public JsonNode toJsonNode () {
+ ObjectNode json = (ObjectNode) super.toJsonNode();
+ json.putAll((ObjectNode) mapper.valueToTree(this));
+ return json;
+ };
};
diff --git a/src/main/java/de/ids_mannheim/korap/response/Match.java b/src/main/java/de/ids_mannheim/korap/response/Match.java
index 3afc4e5..4e1d84f 100644
--- a/src/main/java/de/ids_mannheim/korap/response/Match.java
+++ b/src/main/java/de/ids_mannheim/korap/response/Match.java
@@ -26,6 +26,7 @@
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -60,7 +61,7 @@
private final static Logger log = LoggerFactory.getLogger(Match.class);
// This advices the java compiler to ignore all loggings
- public static final boolean DEBUG = true;
+ public static final boolean DEBUG = false;
// Mapper for JSON serialization
ObjectMapper mapper = new ObjectMapper();
@@ -76,7 +77,6 @@
@JsonIgnore
public int potentialStartPosChar = -1, potentialEndPosChar = -1;
- private String error = null;
private String version;
// TEMPORARILY
@@ -724,26 +724,6 @@
};
- /**
- * Get possible error message.
- */
- // Identical to Result
- public String getError () {
- return this.error;
- };
-
-
- /**
- * Set error message.
- *
- * @param msg
- * The error message.
- */
- public void setError (String msg) {
- this.error = msg;
- };
-
-
public Match setContext (SearchContext context) {
this.context = context;
return this;
@@ -1411,12 +1391,9 @@
// Identical to Result!
- public String toJsonString () {
- ObjectNode json = (ObjectNode) mapper.valueToTree(this);
-
- // Match was no match
- if (json.size() == 0)
- return "{}";
+ public JsonNode toJsonNode () {
+ // ObjectNode json = (ObjectNode) mapper.valueToTree(this);
+ ObjectNode json = (ObjectNode) super.toJsonNode();
if (this.context != null)
json.put("context", this.getContext().toJsonNode());
@@ -1424,6 +1401,16 @@
if (this.version != null)
json.put("version", this.getVersion());
+ return json;
+ };
+
+
+ public String toJsonString () {
+ JsonNode json = (JsonNode) this.toJsonNode();
+
+ // Match was no match
+ if (json.size() == 0)
+ return "{}";
try {
return mapper.writeValueAsString(json);
}
diff --git a/src/main/java/de/ids_mannheim/korap/response/Message.java b/src/main/java/de/ids_mannheim/korap/response/Message.java
index f8f598b..27ece33 100644
--- a/src/main/java/de/ids_mannheim/korap/response/Message.java
+++ b/src/main/java/de/ids_mannheim/korap/response/Message.java
@@ -2,6 +2,7 @@
import java.util.LinkedList;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
@@ -21,7 +22,8 @@
* @author Nils Diewald
* @see de.ids_mannheim.korap.response.Messages
*/
-@JsonAutoDetect
+@JsonInclude(Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Message implements Cloneable {
// Mapper for JSON serialization
ObjectMapper mapper = new ObjectMapper();
diff --git a/src/main/java/de/ids_mannheim/korap/response/Messages.java b/src/main/java/de/ids_mannheim/korap/response/Messages.java
index d9d0627..118e9d0 100644
--- a/src/main/java/de/ids_mannheim/korap/response/Messages.java
+++ b/src/main/java/de/ids_mannheim/korap/response/Messages.java
@@ -3,6 +3,7 @@
import de.ids_mannheim.korap.util.QueryException;
import de.ids_mannheim.korap.response.Message;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
@@ -24,6 +25,8 @@
* @see Notifications
* @see Message
*/
+@JsonInclude(Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
public class Messages implements Cloneable, Iterable<Message> {
// Create object mapper for JSON generation
@@ -249,8 +252,12 @@
*/
public JsonNode toJsonNode () {
ArrayNode messageArray = mapper.createArrayNode();
- for (Message msg : this.messages)
- messageArray.add(msg.toJsonNode());
+
+ for (Message msg : this.messages) {
+
+ messageArray.add((JsonNode) msg.toJsonNode());
+ };
+
return (JsonNode) messageArray;
};
diff --git a/src/main/java/de/ids_mannheim/korap/response/Notifications.java b/src/main/java/de/ids_mannheim/korap/response/Notifications.java
index 0485a0e..4a91b3a 100644
--- a/src/main/java/de/ids_mannheim/korap/response/Notifications.java
+++ b/src/main/java/de/ids_mannheim/korap/response/Notifications.java
@@ -66,6 +66,7 @@
*
* @return {@link Messages} representing all warnings
*/
+ @JsonIgnore
public Messages getWarnings () {
return this.warnings;
};
@@ -94,6 +95,7 @@
* @return The message in case it exists, otherwise
* <code>null</code>
*/
+ @JsonIgnore
public Message getWarning (int index) {
if (this.warnings != null)
return this.warnings.get(index);
@@ -163,6 +165,7 @@
*
* @return The {@link Messages} object representing all errors
*/
+ @JsonIgnore
public Messages getErrors () {
return this.errors;
};
@@ -190,6 +193,7 @@
* @return The message in case it exists, otherwise
* <code>null</code>
*/
+ @JsonIgnore
public Message getError (int index) {
if (this.errors != null)
return this.errors.get(index);
@@ -271,6 +275,7 @@
*
* @return {@link Messages} representing all messages
*/
+ @JsonIgnore
public Messages getMessages () {
return this.messages;
};
@@ -298,6 +303,7 @@
* @return The message in case it exists, otherwise
* <code>null</code>
*/
+ @JsonIgnore
public Message getMessage (int index) {
if (this.messages != null)
return this.messages.get(index);
diff --git a/src/main/java/de/ids_mannheim/korap/response/match/MatchIdentifier.java b/src/main/java/de/ids_mannheim/korap/response/match/MatchIdentifier.java
index 37a6c03..aee9851 100644
--- a/src/main/java/de/ids_mannheim/korap/response/match/MatchIdentifier.java
+++ b/src/main/java/de/ids_mannheim/korap/response/match/MatchIdentifier.java
@@ -9,9 +9,10 @@
private ArrayList<int[]> pos = new ArrayList<>(8);
// TODO: "contains" is necessary for a compatibility bug in Kustvakt
- Pattern idRegex = Pattern.compile("^(?:match-|contains-)(?:([^!]+?)[!\\.])?"
- + "([^!]+)-p([0-9]+)-([0-9]+)"
- + "((?:\\(-?[0-9]+\\)-?[0-9]+--?[0-9]+)*)" + "(?:c.+?)?$");
+ Pattern idRegex = Pattern
+ .compile("^(?:match-|contains-)(?:([^!]+?)[!\\.])?"
+ + "([^!]+)-p([0-9]+)-([0-9]+)"
+ + "((?:\\(-?[0-9]+\\)-?[0-9]+--?[0-9]+)*)" + "(?:c.+?)?$");
Pattern posRegex = Pattern.compile("\\(([0-9]+)\\)([0-9]+)-([0-9]+)");
diff --git a/src/test/java/de/ids_mannheim/korap/collection/TestKrillCollectionJSON.java b/src/test/java/de/ids_mannheim/korap/collection/TestKrillCollectionJSON.java
index ba5a8f6..e518fb6 100644
--- a/src/test/java/de/ids_mannheim/korap/collection/TestKrillCollectionJSON.java
+++ b/src/test/java/de/ids_mannheim/korap/collection/TestKrillCollectionJSON.java
@@ -24,6 +24,7 @@
final String path = "/queries/collections/";
+
@Test
public void collection1 () {
String metaQuery = _getJSONString("collection_1.jsonld");
@@ -42,6 +43,7 @@
+ "[19900000 TO 99999999] +pubDate:[0 TO 20061099])); ");
};
+
@Test
public void collection3 () {
String metaQuery = _getJSONString("collection_3.jsonld");
@@ -66,7 +68,8 @@
assertFalse(ks.hasErrors());
assertFalse(ks.hasWarnings());
assertFalse(ks.hasMessages());
- assertEquals("filter with QueryWrapperFilter(+author:/Goethe/); ", ks.getCollection().toString());
+ assertEquals("filter with QueryWrapperFilter(+author:/Goethe/); ", ks
+ .getCollection().toString());
};
@@ -77,9 +80,11 @@
assertFalse(ks.hasErrors());
assertFalse(ks.hasWarnings());
assertFalse(ks.hasMessages());
- assertEquals("filter with QueryWrapperFilter(-author:/Goethe/); ", ks.getCollection().toString());
+ assertEquals("filter with QueryWrapperFilter(-author:/Goethe/); ", ks
+ .getCollection().toString());
};
+
@Test
public void collectionWithNegativeString () {
String query = _getJSONString("collection_ne.jsonld");
@@ -87,7 +92,8 @@
assertFalse(ks.hasErrors());
assertFalse(ks.hasWarnings());
assertFalse(ks.hasMessages());
- assertEquals("filter with QueryWrapperFilter(-author:Goethe); ", ks.getCollection().toString());
+ assertEquals("filter with QueryWrapperFilter(-author:Goethe); ", ks
+ .getCollection().toString());
};
diff --git a/src/test/java/de/ids_mannheim/korap/index/TestMatchIdentifier.java b/src/test/java/de/ids_mannheim/korap/index/TestMatchIdentifier.java
index 9258455..71926fd 100644
--- a/src/test/java/de/ids_mannheim/korap/index/TestMatchIdentifier.java
+++ b/src/test/java/de/ids_mannheim/korap/index/TestMatchIdentifier.java
@@ -28,6 +28,9 @@
@RunWith(JUnit4.class)
public class TestMatchIdentifier {
+ ObjectMapper mapper = new ObjectMapper();
+
+
@Test
public void identifierExample1 () throws IOException, QueryException {
MatchIdentifier id = new MatchIdentifier("match-c1!d1-p4-20");
@@ -138,12 +141,8 @@
"... [{f/m:acht:b}{f/m:neun:a}] ...", km.getSnippetBrackets());
- km = ki.getMatchInfo("match-c1!d1-p7-9(0)8-8(2)7-8",
- "tokens",
- "f",
- null,
- false,
- false);
+ km = ki.getMatchInfo("match-c1!d1-p7-9(0)8-8(2)7-8", "tokens", "f",
+ null, false, false);
assertEquals("SnippetBrackets (1b)",
"... [{f/m:acht:{f/y:eight:b}}{f/m:neun:{f/y:nine:a}}] ...",
km.getSnippetBrackets());
@@ -182,14 +181,14 @@
+ "<span class=\"more\">" + "</span>" + "</span>",
km.getSnippetHTML());
- ObjectMapper mapper = new ObjectMapper();
JsonNode res = mapper.readTree(km.toJsonString());
assertEquals("tokens", res.at("/field").asText());
assertTrue(res.at("/startMore").asBoolean());
assertTrue(res.at("/endMore").asBoolean());
assertEquals("c1", res.at("/corpusID").asText());
assertEquals("d1", res.at("/docID").asText());
- assertEquals("match-c1!d1-p7-9(4)8-8(2)7-8", res.at("/matchID").asText());
+ assertEquals("match-c1!d1-p7-9(4)8-8(2)7-8", res.at("/matchID")
+ .asText());
assertTrue(res.at("/pubDate").isMissingNode());
};
@@ -507,6 +506,44 @@
};
+ @Test
+ public void indexExampleFailingFoundry () throws IOException,
+ QueryException {
+ KrillIndex ki = new KrillIndex();
+ ki.addDoc(createSimpleFieldDoc4());
+ ki.commit();
+
+ Match km = ki.getMatchInfo("match-c1!d4-p3-9", "tokens", "*", "m",
+ false, false);
+ JsonNode res = mapper.readTree(km.toJsonString());
+ assertEquals("c1", res.at("/corpusID").asText());
+ assertEquals("d4", res.at("/docID").asText());
+ assertEquals("Invalid foundry requested", res.at("/errors/0/1")
+ .asText());
+ };
+
+
+ @Test
+ public void indexExampleNullInfo () throws IOException, QueryException {
+ KrillIndex ki = new KrillIndex();
+ ki.addDoc(createSimpleFieldDoc4());
+ ki.commit();
+ Match km = ki.getMatchInfo("match-c1!d4-p3-9", "tokens", null, null,
+ false, false);
+ JsonNode res = mapper.readTree(km.toJsonString());
+ assertEquals("tokens", res.at("/field").asText());
+ assertTrue(res.at("/startMore").asBoolean());
+ assertTrue(res.at("/endMore").asBoolean());
+ assertEquals("c1", res.at("/corpusID").asText());
+ assertEquals("d4", res.at("/docID").asText());
+ assertEquals(
+ "<span class=\"context-left\"><span class=\"more\"></span></span><mark><span title=\"f/m:vier\"><span title=\"f/y:four\"><span title=\"it/is:4\"><span title=\"x/o:viertens\">a</span></span></span></span><span title=\"f/m:fuenf\"><span title=\"f/y:five\"><span title=\"it/is:5\"><span title=\"x/o:fünftens\">b</span></span></span></span><span title=\"f/m:sechs\"><span title=\"f/y:six\"><span title=\"it/is:6\"><span title=\"x/o:sechstens\">c</span></span></span></span><span title=\"f/m:sieben\"><span title=\"f/y:seven\"><span title=\"it/is:7\"><span title=\"x/o:siebtens\">a</span></span></span></span><span title=\"f/m:acht\"><span title=\"f/y:eight\"><span title=\"it/is:8\"><span title=\"x/o:achtens\">b</span></span></span></span><span title=\"f/m:neun\"><span title=\"f/y:nine\"><span title=\"it/is:9\"><span title=\"x/o:neuntens\">a</span></span></span></span></mark><span class=\"context-right\"><span class=\"more\"></span></span>",
+ res.at("/snippet").asText());
+ assertEquals("match-c1!d4-p3-9", res.at("/matchID").asText());
+ assertTrue(res.at("/pubDate").isMissingNode());
+ };
+
+
private FieldDocument createSimpleFieldDoc () {
FieldDocument fd = new FieldDocument();
fd.addString("corpusID", "c1");
diff --git a/src/test/java/de/ids_mannheim/korap/search/TestMetaFields.java b/src/test/java/de/ids_mannheim/korap/search/TestMetaFields.java
index c43c77a..b48263c 100644
--- a/src/test/java/de/ids_mannheim/korap/search/TestMetaFields.java
+++ b/src/test/java/de/ids_mannheim/korap/search/TestMetaFields.java
@@ -86,7 +86,8 @@
assertEquals("A", res.at("/matches/0/title").asText());
assertEquals("WPD_AAA.00001", res.at("/matches/0/docID").asText());
assertTrue(res.at("/matches/0/textSigle").isMissingNode());
- assertEquals("match-WPD_AAA.00001-p6-7", res.at("/matches/0/matchID").asText());
+ assertEquals("match-WPD_AAA.00001-p6-7", res.at("/matches/0/matchID")
+ .asText());
// assertEquals("p6-7", res.at("/matches/0/matchID").asText());
assertEquals("", res.at("/matches/0/subTitle").asText());
assertEquals("", res.at("/matches/0/textClass").asText());
diff --git a/src/test/java/de/ids_mannheim/korap/search/TestResult.java b/src/test/java/de/ids_mannheim/korap/search/TestResult.java
index 88e3240..6910ffb 100644
--- a/src/test/java/de/ids_mannheim/korap/search/TestResult.java
+++ b/src/test/java/de/ids_mannheim/korap/search/TestResult.java
@@ -75,7 +75,8 @@
*/
assertEquals(1, res.at("/matches/0/UID").asInt());
assertEquals("doc-1", res.at("/matches/0/docID").asText());
- assertEquals("match-doc-1-p0-1(1)0-0", res.at("/matches/0/matchID").asText());
+ assertEquals("match-doc-1-p0-1(1)0-0", res.at("/matches/0/matchID")
+ .asText());
assertEquals(
"<span class=\"context-left\"></span><mark><mark class=\"class-1 level-0\">a</mark></mark><span class=\"context-right\">bab</span>",
res.at("/matches/0/snippet").asText());
@@ -88,7 +89,8 @@
*/
assertEquals(2, res.at("/matches/6/UID").asInt());
assertEquals("doc-2", res.at("/matches/6/docID").asText());
- assertEquals("match-doc-2-p2-3(1)2-2", res.at("/matches/6/matchID").asText());
+ assertEquals("match-doc-2-p2-3(1)2-2", res.at("/matches/6/matchID")
+ .asText());
assertEquals(
"<span class=\"context-left\">ab</span><mark><mark class=\"class-1 level-0\">a</mark></mark><span class=\"context-right\"></span>",
res.at("/matches/6/snippet").asText());