What JSON-LD structured data to use for a multi-pararaph, multi-image blogpost? - json-ld

I have created the following JSON-LD for a blogpost in my blog:
{
"#context": "http://schema.org",
"#type": "BlogPosting",
"mainEntityOfPage": {
"#type": "WebPage",
"#id": "https://www.example.com"
},
"headline": "My Headline",
"articleBody": "blablabla",
"articleSection": "bla",
"description": "Article description",
"inLanguage": "en",
"image": "https://www.example.com/myimage.jpg",
"dateCreated": "2019-01-01T08:00:00+08:00",
"datePublished": "2019-01-01T08:00:00+08:00",
"dateModified": "2019-01-01T08:00:00+08:00",
"author": {
"#type": "Organization",
"name": "My Organization",
"logo": {
"#type": "ImageObject",
"url": "https://www.example.com/logo.jpg"
}
},
"publisher": {
"#type": "Organization",
"name": "Artina Luxury Villa",
"name": "My Organization",
"logo": {
"#type": "ImageObject",
"url": "https://www.example.com/mylogo.jpg"
}
}
}
Now, I have some blog posts that contain multiple paragraphs and each paragraph is accompanied by an image. Any ideas how can I depict such a structure with JSON-LD?
Background
I have created a simple blog which uses a JSON file for 2 purposes: (a) feed the blog with posts instead using a DB (by using XMLHttpRequest and JSON.parse) and (b) to add JSON-LD structured data to the code for SEO purposes.
When I read the JSON file I have to know which image belongs to which paragraph of the text in order to display it correctly.

Note: As you seem to need this only for internal purposes, and as there is typically no need to publically provide data about this kind of structure, I think it would be best not to provide public Schema.org data about it. So you could, for example, use it to build the page, and then remove it again (or whatever works for your case). Then it would also be possible to use a custom vocabulary (under your own domain) for this, if it better fits your needs.
You could use the hasPart property to add a WebPageElement for each paragraph+image block.
Each WebPageElement can have text and image (and, again, hasPart, if you need to nest them).
Note that JSON-LD arrays are unordered by default. You can use #list to make it ordered.
"hasPart": { "#list":
[
{
"#type": "WebPageElement",
"text": "plain text",
"image": "image-1.png"
},
{
"#type": "WebPageElement",
"text": "plain text",
"image": "image-2.png"
}
]
}
For the blog posting’s header/footer, you could use the more specific WPHeader/WPFooter instead of WebPageElement.

Related

How do I compact and/or frame a json-ld document so that IRI values are expressed succinctly as well as keys?

Given an original JSON-LD document like this example, which defines the sources for some thing1:
[
{
"#id": "https://example.com/thing1",
"https://example.com/sources": [
{
"#id": "https://example.com/vocab/countries/EN"
},
{
"#id": "https://example.com/vocab/countries/FR"
}
]
}
]
(I'm simplifying quite a lot - in my real use-case this is larger and generated from RDF data. ex:vocab/countries is a SKOS ConceptScheme including EN and FR as Concepts)
I want to collapse it into something approximating what I'd use to express that in more normal JSON:
{
"#id": "https://example.com/thing1",
"sources": ["EN", "FR"]
}
I find I can use a context to collapse into name/values and shorten the names:
{
"#context": {
"#version": 1.1,
"ex": "https://example.com/",
"sources": {
"#id": "ex:sources",
"#type": "#id"
}
},
"#id": "ex:thing1",
"sources": [
"ex:vocab/countries/EN",
"ex:vocab/countries/FR"
]
}
An important element is "#type": "#id" which collapses the source definitions from (a list of) objects into key/value pairs, and the enclosing context term maps https://example.com/sources to sources.
But I cannot find a way which seems to do the same on the values, so that they become EN and FR instead of ex:vocab/countries/EN and ex:vocab/countries/FR. My experiments with adding #base and #vocab properties to the context don't appear to work like I expected them to.
I also need to do this in a scoped way, so that other properties besides sources can be defined which reference different vocabularies. For instance I might want to include languages, which could include terms from a vocabulary representing English, French, Gaelic, Breton, etc. In other words, I can't just set a global vocabulary or base for the entire document.
Can anyone tell me if this kind of transform is possible, and if so, how to achieve it?
JSON-LD Playground link here
You could set the expected values of sources to #vocab instead of #type and use a scoped context to set the #vocab to use. For example:
{
"#version": 1.1,
"ex": "https://example.com/",
"sources": {
"#id": "ex:sources",
"#type": "#vocab",
"#context": {
"#vocab": "https://example.com/vocab/countries/"
}
}
}
(playground link).
This says to treat the values of playground as vocabulary-relative IRIs, and sets the base of that vocabulary for those values. You should get the following:
{
"#context": {
"#version": 1.1,
"ex": "https://example.com/",
"sources": {
"#id": "ex:sources",
"#type": "#vocab",
"#context": {
"#vocab": "https://example.com/vocab/countries/"
}
}
},
"#id": "ex:thing1",
"sources": [
"EN",
"FR"
]
}

Azure Indoor Maps not rendering

Trying to create floor plan upload to azure indoor maps. It is uploaded using postman and got the tilesetid but when I provide tilesetid in the Azure Indoor maps sample, it is not rendering the image in html file. When I use sample zip file provided by azure it is working fine.
Following the article as shown in Azure Indoor Maps
Autocad settings
Below is the manifest file
{
"version": "1.1",
"directoryInfo": {
"name": "Digital Twins Testing Building",
"streetAddress": "Contoso Way",
"unit": "1",
"locality": "Eastside",
"postalCode": "00000",
"adminDivisions": [
"Contoso City",
"Contoso State",
"United States"
],
"hoursOfOperation": "Mo-Fr 08:00-17:00 open",
"phone": "1 (425) 555-1234",
"website": "www.contoso.com",
"nonPublic": false,
"anchorLatitude": 33.44277,
"anchorLongitude": -112.072754,
"anchorHeightAboveSeaLevel": 1000,
"defaultLevelVerticalExtent": 2
},
"buildingLevels": {
"levels": [{
"levelName": "Ground Level",
"ordinal": 0,
"verticalExtent": 5,
"filename": "./GroundLevelFloorPlan.dwg"
}]
},
"georeference": {
"lat": 33.44277,
"lon": -112.072754,
"angle": 0
},
"dwgLayers": {
"exterior": [
"exterior"
],
"unit": [
"unit"
]
}
}
From the manifest, I see you expressed loading only exterior and unit, and didn't pass the label layer which is what brings labels and let you add more properties for the units (or zones). If you don't see the map, I would suggest checking the conversion results (see here) which is always a good practice. Another good way to troubleshoot is review the content in the dataset via WFS API, for example units via https://atlas.microsoft.com/wfs/datasets//collections/unit/items?api-version=1.0&subscription-key={{subcriptionkey}}

How is ActivityStreams's "to" field on Activities different from the "audience" field?

The ActivityStreams specification explains the difference between to, cc, bto, and bcc in section 5.1. But there's also an audience property, defined as:
one or more entities that represent the total population of entities for which the object can considered to be relevant.
How is this different from "to" and "cc"? In particular, what's the different effect on ActivityPub delivery?
The answer can be found in the Issue list of the ActivityPub spec, in this comment by James M Snell:
audience is used for targeting.
For example, suppose I have an activity that everyone in my company should see show up in their activity feeds, but only certain specific people should be notified, I would end up with something like:
{
//...//
"audience": {
"type": "Organization",
"id": "http://example.org",
"name": "My Organization"
},
"to": ["http://jane.example.org", "http://joe.example.org"],
"cc": ["http://sally.example.org"]
}
Here, the audience property provides a scoping of the overall audience, while the to and cc fields identify specific individuals within that audience that should be notified more directly of the activity.
After this discussion the specification was updated. See Audience targeting and specifically in par. 5.1.1 there is some more clarification on its use:
Activities are rarely isolated events. Often, multiple individual activities will be performed around a similar context or audience. For instance, a collaborators working on a shared project might perform multiple related activities in the process of achieving some goal. Such activities can be logically grouped together using the context property, and scoped to a particular audience using the audience property.
With the following example supplied (Example 144):
{
"#context": "https://www.w3.org/ns/activitystreams",
"summary": "Activities in Project XYZ",
"type": "Collection",
"items": [
{
"summary": "Sally created a note",
"type": "Create",
"id": "http://activities.example.com/1",
"actor": "http://sally.example.org",
"object": {
"summary": "A note",
"type": "Note",
"id": "http://notes.example.com/1",
"content": "A note"
},
"context": {
"type": "http://example.org/Project",
"name": "Project XYZ"
},
"audience": {
"type": "Group",
"name": "Project XYZ Working Group"
},
"to": "http://john.example.org"
},
{
"summary": "John liked Sally's note",
"type": "Like",
"id": "http://activities.example.com/1",
"actor": "http://john.example.org",
"object": "http://notes.example.com/1",
"context": {
"type": "http://example.org/Project",
"name": "Project XYZ"
},
"audience": {
"type": "Group",
"name": "Project XYZ Working Group"
},
"to": "http://sally.example.org"
}
]
}

Best practice for large site

I am working on a large site and want to implement JSON-LD. The site has a large social media following and a lot of artist profiles and articles.
This is what I currently have, (the following code is from Google's guidelines)
Front page
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "Organization",
"name": "Organization name",
"url": "http://www.your-site.com",
"sameAs": [
"http://www.facebook.com/your-profile",
"http://instagram.com/yourProfile",
"http://www.linkedin.com/in/yourprofile",
"http://plus.google.com/your_profile"
]
}
</script>
Content pages
<script type='application/ld+json'>
{
"#context": "http://www.schema.org",
"#type": "WebSite",
"name": "About us",
"url": "http://www.your-site.com/about-us"
}
</script>
Profile pages of each artist:
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "NewsArticle",
"mainEntityOfPage": {
"#type": "WebPage",
"#id": "https://google.com/article"
},
"headline": "Article headline",
"image": [
"https://example.com/photos/1x1/photo.jpg",
"https://example.com/photos/4x3/photo.jpg",
"https://example.com/photos/16x9/photo.jpg"
],
"datePublished": "2015-02-05T08:00:00+08:00",
"dateModified": "2015-02-05T09:20:00+08:00",
"author": {
"#type": "Person",
"name": "John Doe"
},
"publisher": {
"#type": "Organization",
"name": "Google",
"logo": {
"#type": "ImageObject",
"url": "https://google.com/logo.jpg"
}
},
"description": "A most wonderful article"
}
</script>
Do I add one script tag per page or do I add all JSON-LD under one script tag? On the front page I have the "Organization" tag and show the social media links, do I add this on all pages?
You may have multiple script JSON-LD data blocks on a page, but using one script element makes it easier to connect the structured data entities: you can nest entities instead of having to reference their URIs.
What to connect? Your NewsArticle can
provide the WebPage¹ entity as value for the mainEntityOfPage property, and
provide the Organization entity as value for the publisher property.
This is only one possibility. Another one: You could provide the WebPage entity as top-level item and provide the NewsArticle entity as value for the mainEntity property.
If you have to duplicate data (for example, because the Organization is author and publisher, or because it’s the publisher of both, the WebPage and the NewsArticle), you can mix nesting and referencing. Give each entity an #id and wherever you provide this entity as value, also provide its #id.
¹ You are using WebSite, but you probably mean WebPage. Also note that the #context should be http://schema.org, not http://www.schema.org.

Annotating nested structures/values in JSON-LD

Say I have a JSON object with some properties in a nested object.
{
"title": "My Blog Post",
"meta": {
"publishedAt": "2016-08-01T00:00:00Z"
}
}
Is there an easy way I can just add a #context to my top-level object to reach
these properties (i.e. just "pass through" the meta object)? Something along
these lines:
{
"#context": {
"title": "schema:name",
"meta.publishedAt": {
"#type": "xsd:date",
"#id": "schema:datePublished"
}
},
"#id": "/my-article",
"title": "My Blog Post",
"meta": {
"publishedAt": "2016-08-01T00:00:00Z"
}
}
I would like to avoid having to add (duplicate) #id to the nested object, which is how I would otherwise have solved it:
{
"#context": {
"title": "schema:name",
"meta": { "#id": "_:meta", "#container": "#set" },
"publishedAt": {
"#type": "xsd:date",
"#id": "schema:datePublished"
}
},
"#id": "/my-article",
"title": "My Blog Post",
"meta": {
"#id": "/my-article",
"publishedAt": "2016-08-01T00:00:00Z"
}
}
This solution works, but requires duplication, and comes from ethanresnick's
comments on Github about annotating JSON API. He noted in another issue that #context is not "quite expressive enough to annotate the JSON API structure". I was hoping to prove him wrong at least with regards to this issue.
I just discovered that the latest JSON-LD spec includes a new section on nested properties. Defining your context like this should result in the desired output:
{
"#context": {
"title": "schema:name",
"meta": "#nest",
"publishedAt": {
"#type": "xsd:date",
"#id": "schema:datePublished",
"#nest": "meta"
}
},
...
}
If what you're trying to do is eat the meta element, then no, this can't be done in JSON-LD.
There have been discussions about doing an inverse-index that could do something like this, but I don't see an issue. You might create one at https://github.com/json-ld/json-ld.org/issues. At some point the CG, or a newly formed WG will start looking at feature requests for a new version.

Resources