这里我想将JSON文件转换为RDF。这是JSON
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
我找不到将其转换为RDF的正确方法。
答案 0 :(得分:7)
没有标准的方法将JSON解释为RDF。有几种方法可以从JSON文件生成RDF(用Java或其他方式)。您可以简单地使用在Java中实现的JSON解析器,然后提取相关部分并使用RDF的Java库构建RDF图,例如Apache Jena或RDF4J(以前称为 Sesame )。但是,还有其他方法可以使任务更容易:
@context
将JSON文件转换为JSON-LD文件。这适用于简单的案例,但不足以涵盖许多相关案例。免责声明:我为SPARQL-Generate做出了贡献。
答案 1 :(得分:3)
如果你的目标是简单地获得有效的RDF而不做任何关于结构的决定,你可以简单地添加一个@context对象并将现有的JSON转换为JSON-LD,例如。
{
"@context": {"@vocab": "http://example.org/ontology#"},
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
然后可以使用适当的RDF / JSON-LD库将其解释为RDF,RDF结构将是:
@prefix ns0: <http://example.org/ontology#> .
[] ns0:glossary [
ns0:GlossDiv [
ns0:GlossList [ ns0:GlossEntry [
ns0:Abbrev "ISO 8879:1986" ;
ns0:Acronym "SGML" ;
ns0:GlossDef [
ns0:GlossSeeAlso "GML", "XML" ;
ns0:para "A meta-markup language, used to create markup languages such as DocBook."
] ;
ns0:GlossSee "markup" ;
ns0:GlossTerm "Standard Generalized Markup Language" ;
ns0:ID "SGML" ;
ns0:SortAs "SGML"
] ] ;
ns0:title "S"
] ;
ns0:title "example glossary"
] .
这可能是奇怪的RDF,但它可以使用RDF工具加载和操作。
您可以使用json-ld playground
中的示例答案 2 :(得分:3)
您可以使用RML将JSON文件转换为RDF。 为此,您需要首先创建一些映射规则。 RML处理器使用这些映射规则来转换您的输入数据 进入RDF。 RML处理器的一个示例是 RML mapper。
<#LogicalSource>
a rml:logicalSource;
rml:source "data.json";
rml:referenceFormulation ql:JSONPath;
rml:iterator "$.glossary".
此RDF代码段告诉RML处理器他必须检索data.json
并
使用JSONPath表达式(ql:JSONPath
)遍历数据
由rml:iterator
指定。
<#GlossaryMapping>
a rr:TriplesMap;
rml:logicalSource <#LogicalSource>;
rr:subjectMap [
rr:template "http://example.org/glossary/{title}";
];
rr:predicateObjectMap [
rr:predicate ex:title;
rr:objectMap [
rml:reference "title";
];
].
TriplesMap使用创建的LogicalSource访问数据。三元组地图
将确保RML处理器使用
http://example.org/glossary/{title}
作为主语,ex:title
作为谓语,
JSON属性title
作为对象的值
GlossEntry
)的条目输入到更高的元素glossary
例如,您可以编写以下映射规则:<#GlossaryMapping>
a rr:TriplesMap;
rml:logicalSource <#LogicalSource>;
rr:subjectMap [
rr:template "http://example.org/glossary/{title}";
];
rr:predicateObjectMap [
rr:predicate ex:glossDiv;
rr:objectMap [
rr:parentTriplesMap <#GlossListEntryMapping>;
rr:child "GlossDiv.title";
rr:parent "GlossDiv.title";
];
].
<#GlossListEntryMapping>
a rr:TriplesMap;
rml:logicalSource <#LogicalSource>;
rr:subjectMap [
rr:template "http://example.org/entry/{GlossDiv.title}";
];
TripleMaps都将在考虑到
rr:joinCondition
。如果没有提供加入条件,则孩子的每个科目
将会与家长的每个科目一起加入。
映射规则
在此完整示例中,我省略了一些JSON属性以使其简洁。
@base <http://example.org> .
@prefix rr: <http://www.w3.org/ns/r2rml#> .
@prefix rml: <http://semweb.mmlab.be/ns/rml#> .
@prefix ql: <http://semweb.mmlab.be/ns/ql#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix ex: <http://example.org/ns#> .
<#LogicalSource>
a rml:logicalSource;
rml:source "data.json";
rml:referenceFormulation ql:JSONPath;
rml:iterator "$.glossary".
<#GlossaryMapping>
a rr:TriplesMap;
rml:logicalSource <#LogicalSource>;
rr:subjectMap [
rr:template "http://example.org/glossary/{title}";
];
rr:predicateObjectMap [
rr:predicate ex:title;
rr:objectMap [
rml:reference "title";
];
];
rr:predicateObjectMap [
rr:predicate ex:glossDiv;
rr:objectMap [
rr:parentTriplesMap <#GlossListEntryMapping>;
rr:child "GlossDiv.title";
rr:parent "GlossDiv.title";
];
].
<#GlossListEntryMapping>
a rr:TriplesMap;
rml:logicalSource <#LogicalSource>;
rr:subjectMap [
rr:template "http://example.org/entry/{GlossDiv.title}";
];
rr:predicateObjectMap [
rr:predicate ex:ID;
rr:objectMap [
rml:reference "GlossDiv.GlossList.GlossEntry.ID"
];
];
rr:predicateObjectMap [
rr:predicate ex:Abbrev;
rr:objectMap [
rml:reference "GlossDiv.GlossList.GlossEntry.Abbrev"
];
];
# Other properties can be mapped too if needed
rr:predicateObjectMap [
rr:predicate ex:glossSeeAlso;
rr:objectMap [ # Mapping arrays can also be done
rml:reference "GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso.[*]";
];
].
输出
<http://example.org/entry/S> <http://example.org/ns#glossSeeAlso> "GML".
<http://example.org/entry/S> <http://example.org/ns#glossSeeAlso> "XML".
<http://example.org/entry/S> <http://example.org/ns#ID> "SGML".
<http://example.org/entry/S> <http://example.org/ns#Abbrev> "ISO 8879:1986".
<http://example.org/glossary/example%20glossary> <http://example.org/ns#title> "example glossary".
<http://example.org/glossary/example%20glossary> <http://example.org/ns#glossDiv> <http://example.org/entry/S>.
注意:我为RML及其技术做出了贡献。
答案 3 :(得分:1)
如果我理解你的问题,我建议使用Apache的开源语义网库Apache Jena。
我还发现了JSON2RDF,这个项目声称利用Jena创建了一种将JSON转换为RDF的语言,但我自己没有测试过,而且文档含糊不清。如果您最终查看它,请分享您的经验。
答案 4 :(得分:0)
我们已经发布了开源JSON2RDF转换器(不要与vaiden提到的JSON2RDF混淆),它可以使您做到这一点: https://github.com/AtomGraph/JSON2RDF
JSON2RDF + SPARQL可以用作JSON-LD + "S-Port" : "62416",
"CS-Username" : "-",
"CS-URI-Query" : "-"
的更灵活选择。
答案 5 :(得分:0)
我们正在提供JSON到JSONLD转换服务:https://json2ld.mapper.tokyo/
首先,您粘贴或上传JSON数据,然后立即生成其JSONLD版本。
如果JSON数据中有匹配的术语(例如“名称”)被映射到https://schema.org/name,它将自动映射一些现有词汇,例如schema.org。
您可以编辑要映射的词汇或术语,并从GitHub存储库中发布上下文。
答案 6 :(得分:0)
我最近花了一些时间将一些旧的 java 代码粘贴在一起,以创建一个名为“oi”的命令行工具。
https://github.com/jschnasse/oi
致电
oi stack44753298.json -t turtle
印刷品
_:b0 <info:oi/glossary> _:b1 .
_:b1 <info:oi/GlossDiv> _:b2 .
_:b2 <info:oi/GlossList> _:b3 .
_:b3 <info:oi/GlossEntry> _:b4 .
_:b4 <info:oi/Abbrev> "ISO 8879:1986";
<info:oi/Acronym> "SGML";
<info:oi/GlossDef> _:b5 .
_:b5 <info:oi/GlossSeeAlso> "GML", "XML";
<info:oi/para> "A meta-markup language, used to create markup languages such as DocBook." .
_:b4 <info:oi/GlossSee> "markup";
<info:oi/GlossTerm> "Standard Generalized Markup Language";
<info:oi/ID> "SGML";
<info:oi/SortAs> "SGML" .
_:b2 <info:oi/title> "S" .
_:b1 <info:oi/title> "example glossary" .
该工具使用非常粗略的方法将 rdf 转换为 json,反之亦然。对于 json 到 rdf 的情况,它仅通过将所有 json 键放入 info:namespace
来创建临时上下文。之后,它使用上下文将 json 读取为 jsonld。与本主题 by brinxmat 中已经描述的完全一样。
它大致遵循我在最近的 stackoverflow 线程中写的想法:
答案 7 :(得分:-1)
使用此JSON解析器将JSON读取到Java对象,并使用之前读取的Java对象创建rdf。
package your_package;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
<html>
/**
* JSON is an open standard format that uses human-readable text to transmit
* Data objects consisting of attribute–value pairs. It is used primarily to
* Transmit data between a server and web application, as an alternative to XML.
*
* JSON's basic types are:
* <ul>
* <li><b>Number</b>: a signed decimal number that may contain a fractional part
* And may use exponential E notation. JSON does not allow non-numbers like NaN,
* Nor does it make any distinction between integer and floating-point. (Even
* Though JavaScript uses a double-precision floating-point format for all its
* Numeric values, other languages implementing JSON may encode numbers
* differently) </li>
* <li><b>String</b>: a sequence of zero or more Unicode characters. Strings are
* Delimited with double-quotation marks and support a backslash escaping
* syntax.</li>
* <li><b>Boolean</b>: either of the values {@code true} or {@code false}</li>
* <li><b>Array</b>: an ordered list of zero or more values, each of which may
* Be of any type. Arrays use square bracket notation with elements being
* comma-separated.</li>
* <li><b>Object</b>: an unordered collection of name/value pairs where the
* Names (also called keys) are strings. Since objects are intended to represent
* Associative arrays, it is recommended, though not required, that each key is
* Unique within an object. Objects are delimited with curly brackets and use
* Commas to separate each pair, while within each pair the colon {@code ':'}
* Character separates the key or name from its value.</li>
* <li><b>null</b>: An empty value, using the word null</li>
* </ul>
* Conversion table:
* <table border='1'>
* <tr><td>java.util.Map</td><td>JSON Object {"key":[0,2,3]}</td></tr>
* <tr><td>java.util.Collection</td><td>JSON Array [0,1,2,"string"]</td></tr>
* <tr><td>java.lang.String</td><td>JSON String "example"</td></tr>
* <tr><td>java.lang.Boolean</td><td>JSON Boolean (true/false) </td></tr>
* <tr><td>java.lang.Number</td><td>JSON Number (-2.5E2) </td></tr>
* <tr><td>null</td><td>JSON Null (null) </td></tr>
* </table>
* Any other object will be write with the next formula:
* <u>{@code obj.toString()}</u>. For example:
* {@Code write (out, new java.lang.object())}. The output stream will be
* Contains the hashcode of newly created object because the default object
* toString() method returns the object hashcode. This class supported the
* Duplicated keys in the object map.
*
* The JavaScript Object Notation (JSON) Data Interchange Format:
* <A href='http://tools.ietf.org/html/rfc7159'>RFC-7159</a>
*
* @See DuplicatedKeyList
*/
public class Json {
/**
* This field represents when the json object is finished, no more available
* data to processing.
*/
private static final Object close = new Object();
/**
* The step offsets in the rows.
*/
private static final int writeSpaceCount = 1;
/**
* 'n' 'u' 'l' 'l'
*/
public static final byte[] NULL = new byte[]{'n', 'u', 'l', 'l'};
/**
* The null identifer, also called: the first character of null.
*/
public static final int NULL_LOWER = 'n';
/**
* The null identifer, also called: the first character of null (uppercase).
*/
public static final int NULL_UPPER = 'N';
/**
* The first character of {@code true}.
*/
public static final int TRUE = 't';
/**
* The first character of {@code true} (uppercase).
*/
public static final int TRUE_UPPER = 'T';
/**
* The first character of {@code false}.
*/
public static final int FALSE = 'f';
/**
* The first character of {@code false} (uppercase).
*/
public static final int FALSE_UPPER = 'F';
/**
* Colon ascii value
*/
public static final int COLON = ':';
/**
* Comma ascii value
*/
public static final int COMMA = ',';
/**
* left bracket (the list identifier, first character)
*/
public static final int LEFT_BRACKET = '[';
/**
* left brace (the map identifier, first character)
*/
public static final int LEFT_BRACE = '{';
/**
* right bracket (the list identifier, last character)
*/
public static final int RIGHT_BRACKET = ']';
/**
* right bracket (the map identifier, last character)
*/
public static final int RIGHT_BRACE = '}';
/**
* the string identifier: {@code "}
*/
public static final int STRING = '"';
/**
* the space ascii value
*/
public static final int SP = ' ';
/**
* the backslash ascii value
*/
public static final int BS = '\\';
/**
* the CR (carriage return) ascii value
*/
public static final int CR = 13;
/**
* the line feed ascii value
*/
public static final int LF = 10;
/**
* the end of file identifier
*/
public static final int EOF = -1;
/**
* end of line identifier (CR + LF)
*/
public static final byte[] EOL = new byte[]{CR, LF};
/**
* the byte array buffer to read
*/
private final ByteArrayOutputStream buf = new ByteArrayOutputStream();
/**
* Creates a new JSON which can read and write json objects.
*/
public Json() {
}
/**
* Creates a new empty map.
*
* @return a new empty map.
*/
private Map createEmptyMap() {
return new HashMap();
}
/**
* Writes a specified object {@code obj} to a specified output stream
* {@code out}, also called: creates a json document from the specified
* object. Duplicated keys are supported. Conversion table: see JSON class
* javadoc.
*
* @param out the specified output stream
* @param obj the specified object
* @throws IOException If IO Error Occurs.
* @see Json
*/
public void write(PrintStream out, Object obj) throws IOException {
write(out, obj, false);
}
/**
* Writes a specified object {@code obj} to a specified print stream
* {@code out}, also called: creates a json document from the specified
* object. Duplicated keys are supported. Conversion table: see JSON class
* javadoc.
*
* @param out the specified print stream
* @param obj the specified object
* @param format {@code true} if the output is formatted, otherwise
* {@code false}.
* @throws IOException If IO Error Occurs.
* @see Json
* @see DuplicatedKeyList
*/
public void write(PrintStream out, Object obj, boolean format) throws IOException {
write(out, obj, format, 0);
}
/**
* Writes a specified object {@code obj} to a specified print stream
* {@code out}, also called: creates a json document from the specified
* object. Duplicated keys are supported. Conversion table: see JSON class
* javadoc.
*
* @param out the specified print stream
* @param obj the specified object
* @param format {@code true} if the output is formatted, otherwise
* {@code false}.
* @param charset the charset which represents the json document encodings
* @param depth the current depth from the root element
* @throws IOException If IO Error Occurs.
* @see Json
* @see DuplicatedKeyList
*/
private synchronized void write(PrintStream out, Object obj, boolean format, int depth) throws IOException {
if (obj == null) {
out.write(NULL);
out.flush();
return;
}
if (obj instanceof String) {
out.write(STRING);
out.print(escape((String) obj));
out.write(STRING);
out.flush();
return;
} else if (obj instanceof Map) {
out.write(LEFT_BRACE);
Map map = (Map) obj;
Iterator<Map.Entry> it = map.entrySet().iterator();
Map.Entry entry;
while (it.hasNext()) {
entry = it.next();
String key = escape(entry.getKey().toString());
Object val = entry.getValue();
if (val instanceof DuplicatedKeyList) {
writeMulti(out, key, (List) val, format, depth);
} else {
if (format) {
writeBreak(out, depth + writeSpaceCount);
}
write(out, key, format, depth + writeSpaceCount);
out.write(COLON);
if (format) {
writeSpace(out, writeSpaceCount);
}
write(out, val, format, depth + writeSpaceCount);
}
if (it.hasNext()) {
out.write(COMMA);
}
}
if (format) {
writeBreak(out, depth);
}
out.write(RIGHT_BRACE);
out.flush();
return;
} else if (obj instanceof Collection) {
out.write(LEFT_BRACKET);
Iterator it = ((Collection) obj).iterator();
while (it.hasNext()) {
if (format) {
writeBreak(out, depth + writeSpaceCount);
}
write(out, it.next(), format, depth + writeSpaceCount);
if (it.hasNext()) {
out.write(COMMA);
}
}
if (format) {
writeBreak(out, depth);
}
out.write(RIGHT_BRACKET);
out.flush();
return;
}
if (obj instanceof Number || obj instanceof Boolean) {
out.print(obj);
} else {
out.write(STRING);
out.print(escape(obj.toString()));
out.write(STRING);
}
out.flush();
}
/**
* Reads a specified input stream {@code in} which contains json elements
* and returns the java object representation of json elements. Conversion
* table: see JSON class javadoc.
*
* @param in the specified input stream
* @return the java object representation of json elements.
* @throws IOException If IO Error Occurs.
* @see Json
* @see DuplicatedKeyList
*/
public Object read(InputStream in) throws IOException {
return read(in, Charset.forName("UTF-8"));
}
/**
* Reads a specified input stream {@code in} which contains json elements
* and returns the java object representation of json elements. Conversion
* table: see JSON class javadoc.
*
* @param in the specified input stream
* @param charset the json document encodings
* @return the java object representation of json elements.
* @throws IOException If IO Error Occurs.
* @see Json
* @see DuplicatedKeyList
*/
public synchronized Object read(InputStream in, Charset charset) throws IOException {
int b;
while ((b = in.read()) != EOF) {
if (b > 32 && b != COMMA) {
switch (b) {
//list
case LEFT_BRACKET: {
List list = new ArrayList();
Object obj;
while ((obj = read(in, charset)) != close) {
if (obj instanceof Finish) {
list.add(((Finish) obj).val);
break;
} else {
list.add(obj);
}
}
return list;
}
//map
case LEFT_BRACE: {
Map map = createEmptyMap();
Object key;
Object val;
while ((key = read(in, charset)) != close) {
while ((b = in.read()) != COLON) {
if (b == EOF) {
throw new IOException("EOF");
}
}
val = read(in, charset);
if (map.containsKey(key)) {
Object prev = map.get(key);
DuplicatedKeyList list;
if (prev instanceof DuplicatedKeyList) {
list = (DuplicatedKeyList) prev;
//((DuplicatedKeyList) prev).add(val);
} else {
list = new DuplicatedKeyList(new ArrayList());
list.add(prev);
}
list.add(val);
map.put(key, list);
//}
System.err.println("WARNING: duplicated key: " + key);
} else {
if (val instanceof Finish) {
val = ((Finish) val).val;
map.put(key, val);
break;
} else {
map.put(key, val);
}
}
}
return map;
}
//string
case STRING: {
buf.reset();
int a = 0;
while ((b = in.read()) != STRING || a == BS) {
buf.write(b);
a = b;
}
return unescape(buf.toString(charset.name()));
}
case TRUE_UPPER: {
}
//true
case TRUE: {
in.skip(4);
return true;
}
//false
case FALSE_UPPER: {
}
case FALSE: {
in.skip(5);
return false;
}
//null
case NULL_UPPER: {
}
case NULL_LOWER: {
in.skip(4);
return null;
}
//map right brackets
case RIGHT_BRACE: {
}
case RIGHT_BRACKET: {
return close;
}
//number
default: {
buf.reset();
buf.write(b);
while ((b = in.read()) != EOF) {
if (isRegular(b)) {
buf.write(b);
} else {
break;
}
}
String str = buf.toString(charset.name());
Number num;
if (str.indexOf('.') != -1) {
num = Double.valueOf(str);
} else {
num = Long.valueOf(str);
}
if (b == RIGHT_BRACKET || b == RIGHT_BRACE) {
return new Finish(num);
}
return num;
}
}
}
}
return close;
}
private void writeMulti(PrintStream out, Object key, Collection value, boolean format, int depth) throws IOException {
Iterator it = value.iterator();
while (it.hasNext()) {
if (format) {
writeBreak(out, depth + writeSpaceCount);
}
write(out, key, format, depth + writeSpaceCount);
out.write(COLON);
if (format) {
writeSpace(out, writeSpaceCount);
}
write(out, it.next(), format, depth + writeSpaceCount);
if (it.hasNext()) {
out.write(COMMA);
}
}
}
/**
* Returns {@code true} if the specified {@code b} byte is regular
* character, otherwise {@code false}.
*
* @param b the specified byte
* @return {@code true} if the specified {@code b} byte is regular
* character, otherwise {@code false}.
*/
private boolean isRegular(int b) {
return b > 32
&& b != LEFT_BRACKET
&& b != LEFT_BRACE
&& b != COMMA
&& b != RIGHT_BRACKET
&& b != RIGHT_BRACE;
}
/**
* Returns the unescaped string.
*
* @param str the input source
* @return the unescaped string.
*/
private String unescape(String str) {
str = str.replace("\\b", "\b");
str = str.replace("\\f", "\f");
str = str.replace("\\n", "\n");
str = str.replace("\\r", "\r");
str = str.replace("\\t", "\t");
str = str.replace("\\\"", "\"");
return str;
}
/**
* Returns the escaped string.
*
* @param str the input source
* @return the escaped string.
*/
public static String escape(String str) {
str = str.replace("\b", "\\b");
str = str.replace("\f", "\\f");
str = str.replace("\n", "\\n");
str = str.replace("\r", "\\r");
str = str.replace("\t", "\\t");
str = str.replace("\"", "\\\"");
return str;
}
/**
* Writes spaces to a specified output {@code out}.
*
* @param out the specified output
* @param spaceCount the spaces count
* @throws IOException if IO Error Occurs.
*/
private void writeSpace(OutputStream out, int spaceCount) throws IOException {
byte[] b = new byte[spaceCount];
for (int i = 0; i < b.length; i++) {
b[i] = SP;
}
out.write(b);
}
/**
* Writes break line and spaces to a specified output {@code out}.
*
* @param out the specified output
* @param spaceCount the spaces count
* @throws IOException if IO Error Occurs.
*/
private void writeBreak(OutputStream out, int spaceCount) throws IOException {
out.write(EOL);
writeSpace(out, spaceCount);
}
/**
* Creates a new instance of JSON.
*
* @return a new instance of JSON.
*/
public static Json getInstance() {
return new Json();
}
public Object read(byte[] b) throws IOException {
return read(new ByteArrayInputStream(b));
}
/**
* This class can contains json elements to one key. json objects (map) can
* contains duplicate values to one key.
*/
public static class DuplicatedKeyList extends AbstractList {
private List list;
public DuplicatedKeyList(List list) {
if (list == null) {
throw new NullPointerException("list is null");
}
this.list = list;
}
@Override
public void add(int index, Object element) {
list.add(index, element);
}
@Override
public Object set(int index, Object element) {
return list.set(index, element);
}
@Override
public Object remove(int index) {
return list.remove(index);
}
@Override
public Object get(int index) {
return list.get(index);
}
@Override
public int size() {
return list.size();
}
@Override
public String toString() {
Iterator it = iterator();
if (!it.hasNext()) {
return "[]";
}
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
sb.append('@').append('=');
Object e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (!it.hasNext()) {
return sb.append(']').toString();
}
sb.append(',').append(' ');
}
}
}
/**
* This class is a marker class which must use if the json collection (map
* or list) will be finished.
*/
class Finish {
/**
* the last object
*/
private Object val;
/**
* Creates a new instance with the specified {@code val} value.
*
* @param val the specified value
*/
public Finish(Object val) {
this.val = val;
}
}
}