/// <summary>Copies this UniqueNamer.</summary> /// <remarks>Copies this UniqueNamer.</remarks> /// <returns>a copy of this UniqueNamer.</returns> public virtual JsonLD.Core.UniqueNamer Clone() { JsonLD.Core.UniqueNamer copy = new JsonLD.Core.UniqueNamer(this.prefix); copy.counter = this.counter; copy.existing = (JObject)JsonLdUtils.Clone(this.existing); return(copy); }
/// <summary>Copies this UniqueNamer.</summary> /// <remarks>Copies this UniqueNamer.</remarks> /// <returns>a copy of this UniqueNamer.</returns> public virtual JsonLD.Core.UniqueNamer Clone() { JsonLD.Core.UniqueNamer copy = new JsonLD.Core.UniqueNamer(this.prefix); copy.counter = this.counter; copy.existing = (JObject)JsonLdUtils.Clone(this.existing); return copy; }
/// <summary>Hashes all of the quads about a blank node.</summary> /// <remarks>Hashes all of the quads about a blank node.</remarks> /// <param name="id">the ID of the bnode to hash quads for.</param> /// <param name="bnodes">the mapping of bnodes to quads.</param> /// <param name="namer">the canonical bnode namer.</param> /// <returns>the new hash.</returns> private static string HashQuads(string id, IDictionary <string, IDictionary <string, object> > bnodes, UniqueNamer namer) { // return cached hash if (bnodes[id].ContainsKey("hash")) { return((string)bnodes[id]["hash"]); } // serialize all of bnode's quads var quads = (IList <RdfDataset.Quad>)bnodes[id]["quads"]; IList <string> nquads = new List <string>(); for (var i = 0; i < quads.Count; ++i) { object name; nquads.Add(RdfDatasetUtils.ToNQuad(quads[i], quads[i].TryGetValue("name", out name) ? (string)((IDictionary <string, object>)name)["value"] : null, id)); } // sort serialized quads nquads.SortInPlace(StringComparer.Ordinal); // return hashed quads var hash = Sha1hash(nquads); bnodes[id]["hash"] = hash; return(hash); }
/// <summary>Hashes all of the quads about a blank node.</summary> /// <remarks>Hashes all of the quads about a blank node.</remarks> /// <param name="id">the ID of the bnode to hash quads for.</param> /// <param name="bnodes">the mapping of bnodes to quads.</param> /// <param name="namer">the canonical bnode namer.</param> /// <returns>the new hash.</returns> private static string HashQuads(string id, JObject bnodes, UniqueNamer namer) { // return cached hash if (((JObject)bnodes[id]).ContainsKey("hash")) { return((string)((JObject)bnodes[id])["hash"]); } // serialize all of bnode's quads JArray quads = (JArray)((JObject)bnodes[id])["quads"]; IList <string> nquads = new List <string>(); for (int i = 0; i < quads.Count; ++i) { nquads.Add(RDFDatasetUtils.ToNQuad((RDFDataset.Quad)quads[i], quads[i]["name"] != null ? (string)((JObject)quads[i]["name"])["value"] : null, id)); } // sort serialized quads nquads.SortInPlace(); // return hashed quads string hash = Sha1hash(nquads); ((JObject)bnodes[id])["hash"] = hash; return(hash); }
public NormalizeUtils(IList <RDFDataset.Quad> quads, IDictionary <string, IDictionary <string, object> > bnodes, UniqueNamer namer, JsonLdOptions options) { this.options = options; this.quads = quads; this.bnodes = bnodes; this.namer = namer; }
public NormalizeUtils(JArray quads, JObject bnodes, UniqueNamer namer, JsonLdOptions options) { this.options = options; this.quads = quads; this.bnodes = bnodes; this.namer = namer; }
/// <summary>Copies this UniqueNamer.</summary> /// <remarks>Copies this UniqueNamer.</remarks> /// <returns>a copy of this UniqueNamer.</returns> public virtual UniqueNamer Clone() { var copy = new UniqueNamer(prefix); copy.counter = counter; copy.existing = (JObject)JsonLdUtils.Clone(existing); return(copy); }
/// <summary> /// Converts a @list value into linked list of blank node RDF triples (an RDF /// collection). /// </summary> /// <remarks> /// Converts a @list value into linked list of blank node RDF triples (an RDF /// collection). /// </remarks> /// <param name="list">the @list value.</param> /// <param name="namer">a UniqueNamer for assigning blank node names.</param> /// <param name="subject">the subject for the head of the list.</param> /// <param name="predicate">the predicate for the head of the list.</param> /// <param name="triples">the array of triples to append to.</param> private static void ListToRDF(JArray list, UniqueNamer namer, JObject subject, JObject predicate, JArray triples ) { var first = new JObject(); first["type"] = "IRI"; first["value"] = JsonLdConsts.RdfFirst; var rest = new JObject(); rest["type"] = "IRI"; rest["value"] = JsonLdConsts.RdfRest; var nil = new JObject(); nil["type"] = "IRI"; nil["value"] = JsonLdConsts.RdfNil; foreach (var item in list) { var blankNode = new JObject(); blankNode["type"] = "blank node"; blankNode["value"] = namer.GetName(); { var tmp = new JObject(); tmp["subject"] = subject; tmp["predicate"] = predicate; tmp["object"] = blankNode; triples.Add(tmp); } subject = blankNode; predicate = first; JToken @object = ObjectToRDF(item, namer); { var tmp = new JObject(); tmp["subject"] = subject; tmp["predicate"] = predicate; tmp["object"] = @object; triples.Add(tmp); } predicate = rest; } var tmp_1 = new JObject(); tmp_1["subject"] = subject; tmp_1["predicate"] = predicate; tmp_1["object"] = nil; triples.Add(tmp_1); }
// generates unique and duplicate hashes for bnodes /// <exception cref="JsonLD.Core.JsonLdError"></exception> public virtual object HashBlankNodes(IEnumerable <string> unnamed_) { #if !PORTABLE IList <string> unnamed = new List <string>(unnamed_); IList <string> nextUnnamed = new List <string>(); IDictionary <string, IList <string> > duplicates = new Dictionary <string, IList <string > >(); IDictionary <string, string> unique = new Dictionary <string, string>(); // NOTE: not using the same structure as javascript here to avoid // possible stack overflows // hash quads for each unnamed bnode for (int hui = 0; ; hui++) { if (hui == unnamed.Count) { // done, name blank nodes bool named = false; IList <string> hashes = new List <string>(unique.Keys); hashes.SortInPlace(); foreach (string hash in hashes) { string bnode = unique[hash]; namer.GetName(bnode); named = true; } // continue to hash bnodes if a bnode was assigned a name if (named) { // this resets the initial variables, so it seems like it // has to go on the stack // but since this is the end of the function either way, it // might not have to // hashBlankNodes(unnamed); hui = -1; unnamed = nextUnnamed; nextUnnamed = new List <string>(); duplicates = new Dictionary <string, IList <string> >(); unique = new Dictionary <string, string>(); continue; } else { // name the duplicate hash bnods // names duplicate hash bnodes // enumerate duplicate hash groups in sorted order hashes = new List <string>(duplicates.Keys); hashes.SortInPlace(); // process each group for (int pgi = 0; ; pgi++) { if (pgi == hashes.Count) { // done, create JSON-LD array // return createArray(); IList <string> normalized = new List <string>(); // Note: At this point all bnodes in the set of RDF // quads have been // assigned canonical names, which have been stored // in the 'namer' object. // Here each quad is updated by assigning each of // its bnodes its new name // via the 'namer' object // update bnode names in each quad and serialize for (int cai = 0; cai < quads.Count; ++cai) { RDFDataset.Quad quad = quads[cai]; foreach (string attr in new string[] { "subject", "object", "name" }) { if (quad.ContainsKey(attr)) { IDictionary <string, object> qa = (IDictionary <string, object>)quad[attr]; if (qa != null && (string)qa["type"] == "blank node" && ((string)qa["value"]).IndexOf ("_:c14n") != 0) { qa["value"] = namer.GetName((string)qa["value"]); } } } normalized.Add(RDFDatasetUtils.ToNQuad(quad, quad.ContainsKey("name" ) && !(quad["name"] == null) ? (string)((IDictionary <string, object>)((IDictionary <string, object>)quad)["name"])["value"] : null)); } // sort normalized output normalized.SortInPlace(); // handle output format if (options.format != null) { if ("application/nquads".Equals(options.format)) { string rval = string.Empty; foreach (string n in normalized) { rval += n; } return(rval); } else { throw new JsonLdError(JsonLdError.Error.UnknownFormat, options.format); } } string rval_1 = string.Empty; foreach (string n_1 in normalized) { rval_1 += n_1; } return(RDFDatasetUtils.ParseNQuads(rval_1)); } // name each group member IList <string> group = duplicates[hashes[pgi]]; IList <NormalizeUtils.HashResult> results = new List <NormalizeUtils.HashResult>(); for (int n_2 = 0; ; n_2++) { if (n_2 == group.Count) { // name bnodes in hash order results.SortInPlace(new _IComparer_145()); foreach (NormalizeUtils.HashResult r in results) { // name all bnodes in path namer in // key-entry order // Note: key-order is preserved in // javascript foreach (string key in r.pathNamer.Existing().GetKeys()) { namer.GetName(key); } } // processGroup(i+1); break; } else { // skip already-named bnodes string bnode = group[n_2]; if (namer.IsNamed(bnode)) { continue; } // hash bnode paths UniqueNamer pathNamer = new UniqueNamer("_:b"); pathNamer.GetName(bnode); NormalizeUtils.HashResult result = HashPaths(bnode, bnodes, namer, pathNamer); results.Add(result); } } } } } // hash unnamed bnode string bnode_1 = unnamed[hui]; string hash_1 = HashQuads(bnode_1, bnodes, namer); // store hash as unique or a duplicate if (duplicates.ContainsKey(hash_1)) { duplicates[hash_1].Add(bnode_1); nextUnnamed.Add(bnode_1); } else { if (unique.ContainsKey(hash_1)) { IList <string> tmp = new List <string>(); tmp.Add(unique[hash_1]); tmp.Add(bnode_1); duplicates[hash_1] = tmp; nextUnnamed.Add(unique[hash_1]); nextUnnamed.Add(bnode_1); JsonLD.Collections.Remove(unique, hash_1); } else { unique[hash_1] = bnode_1; } } } #else throw new PlatformNotSupportedException(); #endif }
/// <summary> /// Produces a hash for the paths of adjacent bnodes for a bnode, /// incorporating all information about its subgraph of bnodes. /// </summary> /// <remarks> /// Produces a hash for the paths of adjacent bnodes for a bnode, /// incorporating all information about its subgraph of bnodes. This method /// will recursively pick adjacent bnode permutations that produce the /// lexicographically-least 'path' serializations. /// </remarks> /// <param name="id">the ID of the bnode to hash paths for.</param> /// <param name="bnodes">the map of bnode quads.</param> /// <param name="namer">the canonical bnode namer.</param> /// <param name="pathNamer">the namer used to assign names to adjacent bnodes.</param> /// <param name="callback">(err, result) called once the operation completes.</param> private static NormalizeUtils.HashResult HashPaths(string id, IDictionary <string, IDictionary <string, object> > bnodes, UniqueNamer namer, UniqueNamer pathNamer) { #if !PORTABLE MessageDigest md = null; try { // create SHA-1 digest md = MessageDigest.GetInstance("SHA-1"); JObject groups = new JObject(); IList <string> groupHashes; IList <RDFDataset.Quad> quads = (IList <RDFDataset.Quad>)bnodes[id]["quads"]; for (int hpi = 0; ; hpi++) { if (hpi == quads.Count) { // done , hash groups groupHashes = new List <string>(groups.GetKeys()); ((List <string>)groupHashes).Sort(StringComparer.CurrentCultureIgnoreCase); for (int hgi = 0; ; hgi++) { if (hgi == groupHashes.Count) { NormalizeUtils.HashResult res = new NormalizeUtils.HashResult(); res.hash = EncodeHex(md.Digest()); res.pathNamer = pathNamer; return(res); } // digest group hash string groupHash = groupHashes[hgi]; md.Update(JsonLD.JavaCompat.GetBytesForString(groupHash, "UTF-8")); // choose a path and namer from the permutations string chosenPath = null; UniqueNamer chosenNamer = null; NormalizeUtils.Permutator permutator = new NormalizeUtils.Permutator((JArray)groups[groupHash]); while (true) { bool contPermutation = false; bool breakOut = false; JArray permutation = permutator.Next(); UniqueNamer pathNamerCopy = pathNamer.Clone(); // build adjacent path string path = string.Empty; JArray recurse = new JArray(); foreach (string bnode in permutation) { // use canonical name if available if (namer.IsNamed(bnode)) { path += namer.GetName(bnode); } else { // recurse if bnode isn't named in the path // yet if (!pathNamerCopy.IsNamed(bnode)) { recurse.Add(bnode); } path += pathNamerCopy.GetName(bnode); } // skip permutation if path is already >= chosen // path if (chosenPath != null && path.Length >= chosenPath.Length && string.CompareOrdinal (path, chosenPath) > 0) { // return nextPermutation(true); if (permutator.HasNext()) { contPermutation = true; } else { // digest chosen path and update namer md.Update(JsonLD.JavaCompat.GetBytesForString(chosenPath, "UTF-8")); pathNamer = chosenNamer; // hash the nextGroup breakOut = true; } break; } } // if we should do the next permutation if (contPermutation) { continue; } // if we should stop processing this group if (breakOut) { break; } // does the next recursion for (int nrn = 0; ; nrn++) { if (nrn == recurse.Count) { // return nextPermutation(false); if (chosenPath == null || string.CompareOrdinal(path, chosenPath) < 0) { chosenPath = path; chosenNamer = pathNamerCopy; } if (!permutator.HasNext()) { // digest chosen path and update namer md.Update(JsonLD.JavaCompat.GetBytesForString(chosenPath, "UTF-8")); pathNamer = chosenNamer; // hash the nextGroup breakOut = true; } break; } // do recursion string bnode_1 = (string)recurse[nrn]; NormalizeUtils.HashResult result = HashPaths(bnode_1, bnodes, namer, pathNamerCopy); path += pathNamerCopy.GetName(bnode_1) + "<" + result.hash + ">"; pathNamerCopy = result.pathNamer; // skip permutation if path is already >= chosen // path if (chosenPath != null && path.Length >= chosenPath.Length && string.CompareOrdinal (path, chosenPath) > 0) { // return nextPermutation(true); if (!permutator.HasNext()) { // digest chosen path and update namer md.Update(JsonLD.JavaCompat.GetBytesForString(chosenPath, "UTF-8")); pathNamer = chosenNamer; // hash the nextGroup breakOut = true; } break; } } // do next recursion // if we should stop processing this group if (breakOut) { break; } } } } // get adjacent bnode IDictionary <string, object> quad = (IDictionary <string, object>)quads[hpi]; string bnode_2 = GetAdjacentBlankNodeName((IDictionary <string, object>)quad["subject" ], id); string direction = null; if (bnode_2 != null) { // normal property direction = "p"; } else { bnode_2 = GetAdjacentBlankNodeName((IDictionary <string, object>)quad["object"], id ); if (bnode_2 != null) { // reverse property direction = "r"; } } if (bnode_2 != null) { // get bnode name (try canonical, path, then hash) string name; if (namer.IsNamed(bnode_2)) { name = namer.GetName(bnode_2); } else { if (pathNamer.IsNamed(bnode_2)) { name = pathNamer.GetName(bnode_2); } else { name = HashQuads(bnode_2, bnodes, namer); } } // hash direction, property, end bnode name/hash using (MessageDigest md1 = MessageDigest.GetInstance("SHA-1")) { // String toHash = direction + (String) ((Map<String, // Object>) quad.get("predicate")).get("value") + name; md1.Update(JsonLD.JavaCompat.GetBytesForString(direction, "UTF-8")); md1.Update(JsonLD.JavaCompat.GetBytesForString(((string)((IDictionary <string, object>)quad["predicate"])["value"]), "UTF-8")); md1.Update(JsonLD.JavaCompat.GetBytesForString(name, "UTF-8")); string groupHash = EncodeHex(md1.Digest()); if (groups.ContainsKey(groupHash)) { ((JArray)groups[groupHash]).Add(bnode_2); } else { JArray tmp = new JArray(); tmp.Add(bnode_2); groups[groupHash] = tmp; } } } } } catch { // TODO: i don't expect that SHA-1 is even NOT going to be // available? // look into this further throw; } finally { md?.Dispose(); } #else throw new PlatformNotSupportedException(); #endif }
internal static JArray GraphToRDF(JObject graph, UniqueNamer namer) { // use RDFDataset.graphToRDF JArray rval = new JArray(); foreach (string id in graph.GetKeys()) { JObject node = (JObject)graph[id]; JArray properties = new JArray(node.GetKeys()); properties.SortInPlace(); foreach (string property in properties) { var eachProperty = property; JToken items = node[eachProperty]; if ("@type".Equals(eachProperty)) { eachProperty = JSONLDConsts.RdfType; } else { if (JsonLdUtils.IsKeyword(eachProperty)) { continue; } } foreach (JToken item in (JArray)items) { // RDF subjects JObject subject = new JObject(); if (id.IndexOf("_:") == 0) { subject["type"] = "blank node"; subject["value"] = namer.GetName(id); } else { subject["type"] = "IRI"; subject["value"] = id; } // RDF predicates JObject predicate = new JObject(); predicate["type"] = "IRI"; predicate["value"] = eachProperty; // convert @list to triples if (JsonLdUtils.IsList(item)) { ListToRDF((JArray)((JObject)item)["@list"], namer, subject , predicate, rval); } else { // convert value or node object to triple object @object = ObjectToRDF(item, namer); IDictionary <string, object> tmp = new Dictionary <string, object>(); tmp["subject"] = subject; tmp["predicate"] = predicate; tmp["object"] = @object; rval.Add(tmp); } } } } return(rval); }
/// <summary> /// Converts a JSON-LD value object to an RDF literal or a JSON-LD string or /// node object to an RDF resource. /// </summary> /// <remarks> /// Converts a JSON-LD value object to an RDF literal or a JSON-LD string or /// node object to an RDF resource. /// </remarks> /// <param name="item">the JSON-LD value or node object.</param> /// <param name="namer">the UniqueNamer to use to assign blank node names.</param> /// <returns>the RDF literal or RDF resource.</returns> private static JObject ObjectToRDF(JToken item, UniqueNamer namer) { JObject @object = new JObject(); // convert value object to RDF if (JsonLdUtils.IsValue(item)) { @object["type"] = "literal"; JToken value = ((JObject)item)["@value"]; JToken datatype = ((JObject)item)["@type"]; // convert to XSD datatypes as appropriate if (value.Type == JTokenType.Boolean || value.Type == JTokenType.Float || value.Type == JTokenType.Integer) { // convert to XSD datatype if (value.Type == JTokenType.Boolean) { @object["value"] = value.ToString(); @object["datatype"] = datatype.IsNull() ? JSONLDConsts.XsdBoolean : datatype; } else { if (value.Type == JTokenType.Float) { // canonical double representation @object["value"] = string.Format("{0:0.0###############E0}", (double)value); @object["datatype"] = datatype.IsNull() ? JSONLDConsts.XsdDouble : datatype; } else { DecimalFormat df = new DecimalFormat("0"); @object["value"] = df.Format((int)value); @object["datatype"] = datatype.IsNull() ? JSONLDConsts.XsdInteger : datatype; } } } else { if (((IDictionary <string, JToken>)item).ContainsKey("@language")) { @object["value"] = value; @object["datatype"] = datatype.IsNull() ? JSONLDConsts.RdfLangstring : datatype; @object["language"] = ((IDictionary <string, JToken>)item)["@language"]; } else { @object["value"] = value; @object["datatype"] = datatype.IsNull() ? JSONLDConsts.XsdString : datatype; } } } else { // convert string/node object to RDF string id = JsonLdUtils.IsObject(item) ? (string)((JObject)item )["@id"] : (string)item; if (id.IndexOf("_:") == 0) { @object["type"] = "blank node"; @object["value"] = namer.GetName(id); } else { @object["type"] = "IRI"; @object["value"] = id; } } return(@object); }
/// <summary> /// Converts a @list value into linked list of blank node RDF triples (an RDF /// collection). /// </summary> /// <remarks> /// Converts a @list value into linked list of blank node RDF triples (an RDF /// collection). /// </remarks> /// <param name="list">the @list value.</param> /// <param name="namer">a UniqueNamer for assigning blank node names.</param> /// <param name="subject">the subject for the head of the list.</param> /// <param name="predicate">the predicate for the head of the list.</param> /// <param name="triples">the array of triples to append to.</param> private static void ListToRDF(JArray list, UniqueNamer namer, JObject subject, JObject predicate, JArray triples ) { JObject first = new JObject(); first["type"] = "IRI"; first["value"] = JSONLDConsts.RdfFirst; JObject rest = new JObject(); rest["type"] = "IRI"; rest["value"] = JSONLDConsts.RdfRest; JObject nil = new JObject(); nil["type"] = "IRI"; nil["value"] = JSONLDConsts.RdfNil; foreach (JToken item in list) { JObject blankNode = new JObject(); blankNode["type"] = "blank node"; blankNode["value"] = namer.GetName(); { JObject tmp = new JObject(); tmp["subject"] = subject; tmp["predicate"] = predicate; tmp["object"] = blankNode; triples.Add(tmp); } subject = blankNode; predicate = first; JToken @object = ObjectToRDF(item, namer); { JObject tmp = new JObject(); tmp["subject"] = subject; tmp["predicate"] = predicate; tmp["object"] = @object; triples.Add(tmp); } predicate = rest; } JObject tmp_1 = new JObject(); tmp_1["subject"] = subject; tmp_1["predicate"] = predicate; tmp_1["object"] = nil; triples.Add(tmp_1); }
internal static JArray GraphToRDF(JObject graph, UniqueNamer namer) { // use RDFDataset.graphToRDF JArray rval = new JArray(); foreach (string id in graph.GetKeys()) { JObject node = (JObject)graph[id]; JArray properties = new JArray(node.GetKeys()); properties.SortInPlace(); foreach (string property in properties) { var eachProperty = property; JToken items = node[eachProperty]; if ("@type".Equals(eachProperty)) { eachProperty = JSONLDConsts.RdfType; } else { if (JsonLdUtils.IsKeyword(eachProperty)) { continue; } } foreach (JToken item in (JArray)items) { // RDF subjects JObject subject = new JObject(); if (id.IndexOf("_:") == 0) { subject["type"] = "blank node"; subject["value"] = namer.GetName(id); } else { subject["type"] = "IRI"; subject["value"] = id; } // RDF predicates JObject predicate = new JObject(); predicate["type"] = "IRI"; predicate["value"] = eachProperty; // convert @list to triples if (JsonLdUtils.IsList(item)) { ListToRDF((JArray)((JObject)item)["@list"], namer, subject , predicate, rval); } else { // convert value or node object to triple object @object = ObjectToRDF(item, namer); IDictionary<string, object> tmp = new Dictionary<string, object>(); tmp["subject"] = subject; tmp["predicate"] = predicate; tmp["object"] = @object; rval.Add(tmp); } } } } return rval; }
/// <summary> /// Converts a JSON-LD value object to an RDF literal or a JSON-LD string or /// node object to an RDF resource. /// </summary> /// <remarks> /// Converts a JSON-LD value object to an RDF literal or a JSON-LD string or /// node object to an RDF resource. /// </remarks> /// <param name="item">the JSON-LD value or node object.</param> /// <param name="namer">the UniqueNamer to use to assign blank node names.</param> /// <returns>the RDF literal or RDF resource.</returns> private static JObject ObjectToRDF(JToken item, UniqueNamer namer) { JObject @object = new JObject(); // convert value object to RDF if (JsonLdUtils.IsValue(item)) { @object["type"] = "literal"; JToken value = ((JObject)item)["@value"]; JToken datatype = ((JObject)item)["@type"]; // convert to XSD datatypes as appropriate if (value.Type == JTokenType.Boolean || value.Type == JTokenType.Float || value.Type == JTokenType.Integer ) { // convert to XSD datatype if (value.Type == JTokenType.Boolean) { @object["value"] = value.ToString(); @object["datatype"] = datatype.IsNull() ? JSONLDConsts.XsdBoolean : datatype; } else { if (value.Type == JTokenType.Float) { // canonical double representation @object["value"] = string.Format("{0:0.0###############E0}", (double)value); @object["datatype"] = datatype.IsNull() ? JSONLDConsts.XsdDouble : datatype; } else { DecimalFormat df = new DecimalFormat("0"); @object["value"] = df.Format((int)value); @object["datatype"] = datatype.IsNull() ? JSONLDConsts.XsdInteger : datatype; } } } else { if (((IDictionary<string, JToken>)item).ContainsKey("@language")) { @object["value"] = value; @object["datatype"] = datatype.IsNull() ? JSONLDConsts.RdfLangstring : datatype; @object["language"] = ((IDictionary<string, JToken>)item)["@language"]; } else { @object["value"] = value; @object["datatype"] = datatype.IsNull() ? JSONLDConsts.XsdString : datatype; } } } else { // convert string/node object to RDF string id = JsonLdUtils.IsObject(item) ? (string)((JObject)item )["@id"] : (string)item; if (id.IndexOf("_:") == 0) { @object["type"] = "blank node"; @object["value"] = namer.GetName(id); } else { @object["type"] = "IRI"; @object["value"] = id; } } return @object; }