簡體   English   中英

使用 Java 將 JSON 文件轉換為 RDF 格式

[英]Convert JSON file into RDF format using Java

這里我想把 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 的正確方法。

沒有將 JSON 解釋為 RDF 的標准方法。 有幾種方法可以從 JSON 文件生成 RDF(Java 或其他)。 您可以簡單地使用在 Java 中實現的 JSON 解析器,然后提取相關部分並使用 RDF 的 Java 庫(例如Apache JenaRDF4J (以前稱為Sesame ))構建 RDF 圖。 但是,還有其他方法可以使任務變得更容易:

  • 通過向其中添加@context將 JSON 文件轉換為JSON-LD文件。 這適用於簡單的案例,但不足以涵蓋許多相關案例。
  • 使用RML ,一種表達從各種數據格式(包括 JSON)到 RDF 的映射的語言。 它在 Java 中有一個參考實現。 RML是R2RML的擴展,因此也可以將關系數據映射到RDF,如果熟悉R2RML ,就比較容易理解RML的工作原理。 還有一個圖形編輯器,但似乎無法下載。
  • 使用SPARQL-Generate ,一種表達從非 RDF 數據源(包括 JSON)到 RDF 的映射的語言。 它有一個基於 Jena 的參考實現。 它擴展了 SPARQL,所以如果您熟悉 SPARQL,它應該很容易使用。 它可以 在線測試

免責聲明:我為 SPARQL-Generate 做出了貢獻。

如果您的目標是簡單地獲得有效的 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玩這個例子

您可以使用RML將 JSON 文件轉換為 RDF。 為此,您需要先創建一些映射規則。 RML 處理器使用這些映射規則將您的輸入數據轉換為 RDF。 RML 處理器的一個例子是RML 映射器

  1. 創建一個 RML LogicalSource 這描述了 RML 處理器應該如何以及在哪里訪問輸入數據:
<#LogicalSource>
    a rml:logicalSource;
    rml:source "data.json";
    rml:referenceFormulation ql:JSONPath;
    rml:iterator "$.glossary".

這個 RDF 片段告訴 RML 處理器他必須檢索data.json並使用rml:iterator指定的 JSONPath 表達式 ( ql:JSONPath ) rml:iterator

  1. 創建一個TriplesMap 這提供了有關如何將輸入數據轉換為 RDF 的 RML 處理器信息。 為提供的數據給出了一個示例:
<#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 來訪問數據。 TriplesMap 將確保 RML 處理器創建以http://example.org/glossary/{title}作為主語、 ex:title作為謂詞和 JSON 屬性title作為對象的三元組

  1. TriplesMap 也可以相互鏈接。 例如,如果您有一個列表條目 ( 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}";
    ];

考慮到提供的rr:joinCondition兩個 TriplesMap 將相互連接。 如果未提供加入條件,則子項的每個主題都將與父項的每個主題相連。

映射規則

為了保持簡潔,我在這個完整示例中省略了一些 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 及其技術做出了貢獻。

如果我正確理解您的問題,我建議使用Apache Jena ,Apache 的開源語義網絡庫。

這是一個RDF 創建教程

我還發現了JSON2RDF ,這是一個聲稱利用 Jena 創建將 JSON 轉換為 RDF 的聲明式語言的項目,但我自己沒有測試過,而且文檔含糊不清。 如果您最終研究它,請分享您的經驗。

我們已經發布了開源 JSON2RDF 轉換器(不要與 vaiden 提到的 JSON2RDF 混淆),它允許您做到這一點: https : //github.com/AtomGraph/JSON2RDF

JSON2RDF + SPARQL 可以用作 JSON-LD + @context的更靈活的替代方案。

我們提供 JSON 到 JSONLD 的轉換服務: https ://json2ld.mapper.tokyo/

首先,您粘貼或上傳您的 JSON 數據,然后它會立即生成它們的 JSONLD 版本。

如果 JSON 數據中存在匹配的術語(例如映射到https://schema.org/name 的“name”),它會自動映射一些現有詞匯表,例如 schema.org。

您可以編輯映射的詞匯表或術語,並從您的 GitHub 存儲庫發布您的上下文。

我最近花了一些時間將一些舊的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。 brinxmat在此線程中已經描述的完全一樣。

它大致遵循我在最近的 stackoverflow 線程中寫的想法:

使用此 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;
        }

    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM