You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stanbol.apache.org by fc...@apache.org on 2011/07/12 17:20:23 UTC
svn commit: r1145631 -
/incubator/stanbol/trunk/commons/jsonld/src/main/java/org/apache/stanbol/commons/jsonld/JsonLdParser.java
Author: fchrist
Date: Tue Jul 12 15:20:23 2011
New Revision: 1145631
URL: http://svn.apache.org/viewvc?rev=1145631&view=rev
Log:
STANBOL-220 Fixed bug parsing lists/arrays
Modified:
incubator/stanbol/trunk/commons/jsonld/src/main/java/org/apache/stanbol/commons/jsonld/JsonLdParser.java
Modified: incubator/stanbol/trunk/commons/jsonld/src/main/java/org/apache/stanbol/commons/jsonld/JsonLdParser.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/commons/jsonld/src/main/java/org/apache/stanbol/commons/jsonld/JsonLdParser.java?rev=1145631&r1=1145630&r2=1145631&view=diff
==============================================================================
--- incubator/stanbol/trunk/commons/jsonld/src/main/java/org/apache/stanbol/commons/jsonld/JsonLdParser.java (original)
+++ incubator/stanbol/trunk/commons/jsonld/src/main/java/org/apache/stanbol/commons/jsonld/JsonLdParser.java Tue Jul 12 15:20:23 2011
@@ -1,6 +1,8 @@
package org.apache.stanbol.commons.jsonld;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.codehaus.jettison.json.JSONArray;
@@ -12,192 +14,240 @@ import org.slf4j.LoggerFactory;
/**
* The JsonLdParser can be used to parse a given JSON-LD String representation
* into a JSON-LD data structure.
- *
+ *
* @author Fabian Christ
*/
public class JsonLdParser extends JsonLdParserCommon {
- private static Logger logger = LoggerFactory.getLogger(JsonLdParser.class);
+ private static Logger logger = LoggerFactory.getLogger(JsonLdParser.class);
- /**
- * Parse the given String into a JSON-LD data structure.
- *
- * @param jsonLdString A JSON-LD String.
- * @return JSON-LD data structure.
- */
- public static JsonLd parse(String jsonLdString) throws Exception {
- JsonLd jld = null;
-
- JSONObject jo = parseJson(jsonLdString);
- if (jo != null) {
- jld = new JsonLd();
- parseSubject(jo, jld, 1, null);
- }
-
- return jld;
- }
-
- /**
- * Parses a single subject.
- *
- * @param jo
- * JSON object that holds the subject's data.
- * @param jld
- * JsonLd object to add the created subject resource.
- */
- private static void parseSubject(JSONObject jo, JsonLd jld, int bnodeCount, String profile) {
-
- // The root subject is used for cases where no explicit subject is specified. We need
- // at least one dummy subject (bnode) to support type coercion because types are assigned to
- // subjects.
- JsonLdResource subject = new JsonLdResource();
-
- try {
- if (jo.has(JsonLdCommon.CONTEXT)) {
- JSONObject context = jo.getJSONObject(JsonLdCommon.CONTEXT);
- for (int i = 0; i < context.names().length(); i++) {
- String name = context.names().getString(i).toLowerCase();
- if (name.equals(JsonLdCommon.TYPES)) {
- JSONObject typeObject = context.getJSONObject(name);
- for (int j = 0; j < typeObject.names().length(); j++) {
- String property = typeObject.names().getString(j);
- String type = typeObject.getString(property);
- subject.putCoercionType(property, type);
- }
- } else {
- jld.addNamespacePrefix(context.getString(name), name);
- }
- }
-
- jo.remove(JsonLdCommon.CONTEXT);
- }
-
- // If there is a local profile specified for this subject, we
- // use that one. Otherwise we assign the profile given by the parameter.
- if (jo.has(JsonLdCommon.PROFILE)) {
- String localProfile = unCURIE(jo.getString(JsonLdCommon.PROFILE), jld.getNamespacePrefixMap());
- profile = localProfile;
- jo.remove(JsonLdCommon.PROFILE);
- }
- subject.setProfile(profile);
-
- if (jo.has(JsonLdCommon.SUBJECT)) {
- // Check for N subjects
- Object subjectObject = jo.get(JsonLdCommon.SUBJECT);
- if (subjectObject instanceof JSONArray) {
- // There is an array of subjects. We create all subjects
- // in sequence.
- JSONArray subjects = (JSONArray) subjectObject;
- for (int i = 0; i < subjects.length(); i++) {
- parseSubject(subjects.getJSONObject(i), jld, bnodeCount++, profile);
- }
- } else {
- String subjectName = unCURIE(jo.getString(JsonLdCommon.SUBJECT), jld.getNamespacePrefixMap());
- subject.setSubject(subjectName);
- }
- jo.remove(JsonLdCommon.SUBJECT);
- } else {
- // No subject specified. We create a dummy bnode
- // and add this subject.
- subject.setSubject("_:bnode" + bnodeCount);
- jld.put(subject.getSubject(), subject);
- }
-
- // Iterate through the rest of properties and unCURIE property values
- // depending on their type
- if (jo.names() != null && jo.names().length() > 0) {
- for (int i = 0; i < jo.names().length(); i++) {
- String property = jo.names().getString(i);
- Object valueObject = jo.get(property);
- if (valueObject instanceof JSONObject) {
- JSONObject jsonValue = (JSONObject) valueObject;
- subject.putProperty(property, convertToMapAndList(jsonValue, jld
- .getNamespacePrefixMap()));
- } else if (valueObject instanceof String) {
- String stringValue = (String) valueObject;
- subject.putProperty(property, unCURIE(stringValue, jld.getNamespacePrefixMap()));
- } else {
- subject.putProperty(property, valueObject);
- }
- }
- }
-
- } catch (JSONException e) {
- logger.error("There were JSON problems when parsing the JSON-LD String", e);
- e.printStackTrace();
- }
- }
-
- /**
- * Converts a JSON object into a Map or List data structure.
- *
- * <p>
- * The JSON-LD implementation is based on Map and List data types. If the input is a JSONObject, it will
- * be converted into a Map<String, Object>. If the input is a JSONArray, it will be converted into a
- * List<Object>. Otherwise the input will be returned untouched.
- *
- * @param input
- * Object that will be converted.
- * @return
- */
- private static Object convertToMapAndList(Object input, Map<String,String> namespacePrefixMap) {
- if (input instanceof JSONObject) {
- JSONObject jo = (JSONObject) input;
-
- // Handle IRIs
- if (jo.has(JsonLdCommon.IRI)) {
- try {
- return new JsonLdIRI(unCURIE(jo.getString(JsonLdCommon.IRI), namespacePrefixMap));
- } catch (JSONException e) {
- return null;
- }
- }
- else {
- // Handle arbitrary JSON
- return convertToMap(jo, namespacePrefixMap);
- }
- } else if (input instanceof String) {
- return unCURIE((String) input, namespacePrefixMap);
- } else {
- return input;
- }
- }
-
- /**
- * Converts a JSONOBject into a Map<String, Object>.
- *
- * @param jo
- * JSONOBject to be converted.
- * @return A Map that represents the same information as the JSONOBject.
- */
- private static Map<String,Object> convertToMap(JSONObject jo, Map<String,String> namespacePrefixMap) {
- Map<String,Object> jsonMap = null;
- try {
- if (jo.names() != null && jo.names().length() > 0) {
- jsonMap = new HashMap<String,Object>();
- for (int i = 0; i < jo.names().length(); i++) {
- String name = jo.names().getString(i);
- jsonMap.put(name, convertToMapAndList(jo.get(name), namespacePrefixMap));
- }
- }
- } catch (JSONException e) { /* ignored */}
- return jsonMap;
- }
-
- /**
- * Replaces the CURIE prefixes with the namespace to create full qualified IRIs.
- *
- * @param curie
- * The CURIE to create an IRI from.
- * @param namespacePrefixMap
- * A Map with known namespaces.
- * @return
- */
- private static String unCURIE(String curie, Map<String,String> namespacePrefixMap) {
- for (String namespace : namespacePrefixMap.keySet()) {
- String prefix = namespacePrefixMap.get(namespace) + ":";
- curie = curie.replaceAll(prefix, namespace);
- }
- return curie;
- }
+ /**
+ * Parse the given String into a JSON-LD data structure.
+ *
+ * @param jsonLdString
+ * A JSON-LD String.
+ * @return JSON-LD data structure.
+ */
+ public static JsonLd parse(String jsonLdString) throws Exception {
+ JsonLd jld = null;
+
+ JSONObject jo = parseJson(jsonLdString);
+ if (jo != null) {
+ jld = new JsonLd();
+ parseSubject(jo, jld, 1, null);
+ }
+
+ return jld;
+ }
+
+ /**
+ * Parses a single subject.
+ *
+ * @param jo
+ * JSON object that holds the subject's data.
+ * @param jld
+ * JsonLd object to add the created subject resource.
+ */
+ private static void parseSubject(JSONObject jo, JsonLd jld, int bnodeCount,
+ String profile) {
+
+ // The root subject is used for cases where no explicit subject is
+ // specified. We need
+ // at least one dummy subject (bnode) to support type coercion because
+ // types are assigned to
+ // subjects.
+ JsonLdResource subject = new JsonLdResource();
+
+ try {
+ if (jo.has(JsonLdCommon.CONTEXT)) {
+ JSONObject context = jo.getJSONObject(JsonLdCommon.CONTEXT);
+ for (int i = 0; i < context.names().length(); i++) {
+ String name = context.names().getString(i).toLowerCase();
+ if (name.equals(JsonLdCommon.TYPES)) {
+ JSONObject typeObject = context.getJSONObject(name);
+ for (int j = 0; j < typeObject.names().length(); j++) {
+ String property = typeObject.names().getString(j);
+ String type = typeObject.getString(property);
+ subject.putCoercionType(property, type);
+ }
+ } else {
+ jld.addNamespacePrefix(context.getString(name), name);
+ }
+ }
+
+ jo.remove(JsonLdCommon.CONTEXT);
+ }
+
+ // If there is a local profile specified for this subject, we
+ // use that one. Otherwise we assign the profile given by the
+ // parameter.
+ if (jo.has(JsonLdCommon.PROFILE)) {
+ String localProfile = unCURIE(jo
+ .getString(JsonLdCommon.PROFILE), jld
+ .getNamespacePrefixMap());
+ profile = localProfile;
+ jo.remove(JsonLdCommon.PROFILE);
+ }
+ subject.setProfile(profile);
+
+ if (jo.has(JsonLdCommon.SUBJECT)) {
+ // Check for N subjects
+ Object subjectObject = jo.get(JsonLdCommon.SUBJECT);
+ if (subjectObject instanceof JSONArray) {
+ // There is an array of subjects. We create all subjects
+ // in sequence.
+ JSONArray subjects = (JSONArray) subjectObject;
+ for (int i = 0; i < subjects.length(); i++) {
+ parseSubject(subjects.getJSONObject(i), jld,
+ bnodeCount++, profile);
+ }
+ } else {
+ String subjectName = unCURIE(jo
+ .getString(JsonLdCommon.SUBJECT), jld
+ .getNamespacePrefixMap());
+ subject.setSubject(subjectName);
+ }
+ jo.remove(JsonLdCommon.SUBJECT);
+ } else {
+ // No subject specified. We create a dummy bnode
+ // and add this subject.
+ subject.setSubject("_:bnode" + bnodeCount);
+ jld.put(subject.getSubject(), subject);
+ }
+
+ // Iterate through the rest of properties and unCURIE property
+ // values
+ // depending on their type
+ if (jo.names() != null && jo.names().length() > 0) {
+ for (int i = 0; i < jo.names().length(); i++) {
+ String property = jo.names().getString(i);
+ Object valueObject = jo.get(property);
+ handleProperty(jld, subject, property, valueObject);
+ }
+ }
+
+ } catch (JSONException e) {
+ logger.error(
+ "There were JSON problems when parsing the JSON-LD String",
+ e);
+ e.printStackTrace();
+ }
+ }
+
+ private static void handleProperty(JsonLd jld, JsonLdResource subject,
+ String property, Object valueObject) {
+ if (valueObject instanceof JSONObject) {
+ JSONObject jsonValue = (JSONObject) valueObject;
+ subject.putProperty(property, convertToMapAndList(jsonValue, jld
+ .getNamespacePrefixMap()));
+ } else if (valueObject instanceof JSONArray) {
+ JSONArray arrayValue = (JSONArray) valueObject;
+ subject.putProperty(property, convertToMapAndList(arrayValue, jld
+ .getNamespacePrefixMap()));
+ } else if (valueObject instanceof String) {
+ String stringValue = (String) valueObject;
+ subject.putProperty(property, unCURIE(stringValue, jld
+ .getNamespacePrefixMap()));
+ } else {
+ subject.putProperty(property, valueObject);
+ }
+ }
+
+ /**
+ * Converts a JSON object into a Map or List data structure.
+ *
+ * <p>
+ * The JSON-LD implementation is based on Map and List data types. If the
+ * input is a JSONObject, it will be converted into a Map<String,
+ * Object>. If the input is a JSONArray, it will be converted into a
+ * List<Object>. Otherwise the input will be returned untouched.
+ *
+ * @param input
+ * Object that will be converted.
+ * @return
+ */
+ private static Object convertToMapAndList(Object input,
+ Map<String, String> namespacePrefixMap) {
+ if (input instanceof JSONObject) {
+ JSONObject jo = (JSONObject) input;
+
+ // Handle IRIs
+ if (jo.has(JsonLdCommon.IRI)) {
+ try {
+ return new JsonLdIRI(unCURIE(
+ jo.getString(JsonLdCommon.IRI), namespacePrefixMap));
+ } catch (JSONException e) {
+ return null;
+ }
+ } else {
+ // Handle arbitrary JSON
+ return convertToMap(jo, namespacePrefixMap);
+ }
+ } else if (input instanceof JSONArray) {
+ JSONArray ao = (JSONArray) input;
+ return convertToList(ao, namespacePrefixMap);
+ } else if (input instanceof String) {
+ return unCURIE((String) input, namespacePrefixMap);
+ } else {
+ return input;
+ }
+ }
+
+ /**
+ * Converts a JSONOBject into a Map<String, Object>.
+ *
+ * @param jo
+ * JSONOBject to be converted.
+ * @return A Map that represents the same information as the JSONOBject.
+ */
+ private static Map<String, Object> convertToMap(JSONObject jo,
+ Map<String, String> namespacePrefixMap) {
+ Map<String, Object> jsonMap = null;
+ try {
+ if (jo.names() != null && jo.names().length() > 0) {
+ jsonMap = new HashMap<String, Object>();
+ for (int i = 0; i < jo.names().length(); i++) {
+ String name = jo.names().getString(i);
+ jsonMap.put(name, convertToMapAndList(jo.get(name),
+ namespacePrefixMap));
+ }
+ }
+ } catch (JSONException e) { /* ignored */
+ }
+ return jsonMap;
+ }
+
+ private static List<Object> convertToList(JSONArray arrayValue,
+ Map<String, String> namespacePrefixMap) {
+
+ List<Object> values = new ArrayList<Object>();
+ for (int i=0; i<arrayValue.length(); i++) {
+ try {
+ values.add(convertToMapAndList(arrayValue.get(i), namespacePrefixMap));
+ } catch (JSONException e) {
+ logger.error("Error converting JSONArray to list", e);
+ }
+ }
+
+ return values;
+ }
+
+ /**
+ * Replaces the CURIE prefixes with the namespace to create full qualified
+ * IRIs.
+ *
+ * @param curie
+ * The CURIE to create an IRI from.
+ * @param namespacePrefixMap
+ * A Map with known namespaces.
+ * @return
+ */
+ private static String unCURIE(String curie,
+ Map<String, String> namespacePrefixMap) {
+ for (String namespace : namespacePrefixMap.keySet()) {
+ String prefix = namespacePrefixMap.get(namespace) + ":";
+ curie = curie.replaceAll(prefix, namespace);
+ }
+ return curie;
+ }
}