Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ Please:

---

## JSON-LD 0.1.2

* Aliasing Url to Uri (#12)
* Supporting direct JSON-LD content links (#27) (Thanks @AniTexs!)
* Generating README.md (#28)

---

## JSON-LD 0.1.1

* Updating Examples (#13)
Expand Down
175 changes: 110 additions & 65 deletions Commands/Get-JsonLD.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function Get-JsonLD {
param(
# The URL that may contain JSON-LD data
[Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
[Alias('href')]
[Alias('href','uri')]
[Uri]
$Url,

Expand All @@ -42,10 +42,8 @@ function Get-JsonLD {
[string]
$as = 'jsonld',

[switch]
$RawHtml,

# If set, will force the request to be made even if the URL has already been cached.
[Alias('IgnoreCache')]
[switch]
$Force
)
Expand All @@ -71,53 +69,140 @@ application/ld\+json # The type that indicates linked d
$script:Cache = [Ordered]@{}
}

# Construct a filter to match and output
filter matchAndOutput {

$contentToMatch = $_
if ($contentToMatch -match '^\s{0,}\{') {
$contentToMatch = "<script type='application/ld+json'>$($contentToMatch)</script>"
}

if ($as -eq 'html') {
return $contentToMatch
}

# Find all linked data tags within the response
foreach ($match in $linkedDataRegex.Matches("$($contentToMatch)")) {
# If we want the result as xml
if ($As -eq 'xml') {
# try to cast it
$matchXml ="$match" -as [xml]
if ($matchXml) {
# and output it if found.
$matchXml
continue
} else {
# otherwise, fall back to the `<script>` tag
$As = 'script'
}
}

# If we want the tag, that should be the whole match
if ($As -eq 'script') {
"$match"
continue
}

# If we want it as json, we have a match group.
if ($As -eq 'json') {
$match.Groups['JsonContent'].Value
continue
}
# Otherwise, we want it as linked data, so convert from the json
foreach ($jsonObject in
$match.Groups['JsonContent'].Value |
ConvertFrom-Json
) {
# If there was a `@type` or `@graph` property
if (
$jsonObject.'@type' -or
$jsonObject.'@graph'
) {
# output the object as jsonld
$jsonObject | output
continue
}
# If there is neither a `@type` or a `@graph`
else {
# just output the object.
$jsonObject
}
}
}

}

# Construct a filter to output out content

filter output {
# We want JSON-LD types to become .pstypenames, and this should happen recursively.
$in = $_
# we can use `MyInvocation.MyCommand` to anonymously recurse
# (this makes it easier if the name of this command changes)
$mySelf = $MyInvocation.MyCommand

# Context could be a string or an object
# When it is a string, it is a root type.
if ($in.'@context' -is [string]) {
$context = $in.'@context'
$context = $in.'@context' # so set the context
# ( this variable will leek down into lower scopes )
# ( so we can reuse common contexts (like `schema.org` ))
}

# If we have a graph of outputs
if ($in.'@graph') {
# decorate the entire graph as `application/ld+json`
if ($in.pstypenames -ne 'application/ld+json') {
$in.pstypenames.insert(0,'application/ld+json')
}
# and then call ourself
foreach ($graphObject in $in.'@graph') {
# (null the return so we only output the topmost object)
$null = $graphObject |
& $mySelf
}
}
# If we have a single type of object
elseif ($in.'@type') {

# combine it with the context to get our typename
$typeName = if ($context) {
$context, $in.'@type' -join '/'
} else {
$in.'@type'
}

# Decorate the type as `application/ld+json`
if ($in.pstypenames -ne 'application/ld+json') {
$in.pstypenames.insert(0,'application/ld+json')
}
# and decocate the item as the `$typeName`
if ($in.pstypenames -ne $typeName) {
$in.pstypenames.insert(0,$typeName)
}

# Then go over each property
foreach ($property in $in.psobject.properties) {
# if the property had a `@type`
if ($property.value.'@type') {
# call ourself on the value
# (null the return so we only output the topmost object)
$null = $property.value |
& $mySelf
}
}
}
}
}

# Now that we've finished decorating out graph or type
# output our modified input.
$in
}

# Files will be treated as .json
$foreachFile = {
$inFile = $_.FullName
try {

try {
Get-Content -LiteralPath $_.FullName -Raw |
ConvertFrom-Json |
output
matchAndOutput
} catch {
Write-Verbose "$($inFile.FullName) : $_"
}
Expand Down Expand Up @@ -151,63 +236,23 @@ application/ld\+json # The type that indicates linked d

$restResponse =
if ($Force -or -not $script:Cache[$url]) {
$script:Cache[$url] = Invoke-RestMethod -Uri $Url
$script:Cache[$url] = Invoke-WebRequest -Uri $Url
$script:Cache[$url]
} else {
$script:Cache[$url]
}

if ($as -eq 'html') {
return $restResponse
}

# Find all linked data tags within the response
foreach ($match in $linkedDataRegex.Matches("$restResponse")) {
# If we want the result as xml
if ($As -eq 'xml') {
# try to cast it
$matchXml ="$match" -as [xml]
if ($matchXml) {
# and output it if found.
$matchXml
continue
} else {
# otherwise, fall back to the `<script>` tag
$As = 'script'
}
}

# If we want the tag, that should be the whole match
if ($As -eq 'script') {
"$match"
continue
}

# If we want it as json, we have a match group.
if ($As -eq 'json') {
$match.Groups['JsonContent'].Value
continue
}
# Otherwise, we want it as linked data, so convert from the json
foreach ($jsonObject in
$match.Groups['JsonContent'].Value |
ConvertFrom-Json
) {
# If there was a `@type` or `@graph` property
if (
$jsonObject.'@type' -or
$jsonObject.'@graph'
) {
# output the object as jsonld
$jsonObject | output
continue
}
# If there is neither a `@type` or a `@graph`
else {
# just output the object.
$jsonObject
}
}
}

if ($restResponse.Headers['Content-Type'] -match 'json') {
if ($restResponse.Content -is [byte[]]) {
[Text.Encoding]::UTF8.GetString($restResponse.Content) | matchAndOutput
} else {
$restResponse.Content | matchAndOutput
}
} elseif ($restResponse.Content -is [string]) {
$restResponse.Content | matchAndOutput
} else {
""
}
}
}
30 changes: 15 additions & 15 deletions JSON-LD.psd1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@{
RootModule = 'JSON-LD.psm1'
ModuleVersion = '0.1.1'
ModuleVersion = '0.1.2'
GUID = '4e65477c-012c-4077-87c7-3e07964636ce'
Author = 'James Brundage'
CompanyName = 'Start-Automating'
Expand All @@ -16,22 +16,23 @@
# A URL to the license for this module.
ProjectURI = 'https://github.com/PoshWeb/JSON-LD'
LicenseURI = 'https://github.com/PoshWeb/JSON-LD/blob/main/LICENSE'
PSIntro = @'
Get JSON Linked Data with PowerShell

Gets information stored in a page's [json-ld](https://json-ld.org/) (json linked data)

Many pages expose this information for search engine optimization.

This module lets you easily get and work with JSON-LD objects.
'@
ReleaseNotes = @'
---

## JSON-LD 0.1.1
## JSON-LD 0.1.2

* Updating Examples (#13)
* Simplfiying module scaffolding (#15)
* Building types with EZOut (#5)
* Supporting file input (#23)
* `Get-JSONLD -as`
* `Get-JSONLD -as json` (#16)
* `Get-JSONLD -as html` (#17)
* `Get-JSONLD -as script` (#18)
* `Get-JSONLD -as xml` (#19)
* Adding conversion to JsonSchema (#21)
* Adding conversion to At Protocol Lexicons (#22)
* Aliasing Url to Uri (#12)
* Supporting direct JSON-LD content links (#27) (Thanks @AniTexs!)
* Generating README.md (#28)

---

Expand All @@ -45,5 +46,4 @@ Additional History in [CHANGELOG](https://github.com/PoshWeb/JSON-LD/blob/main/C
}
}

}

}
63 changes: 53 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,69 @@
# JSON-LD

[![JSON-LD](https://img.shields.io/powershellgallery/dt/JSON-LD)](https://www.powershellgallery.com/packages/JSON-LD/)
## Get JSON Linked Data with PowerShell
Get JSON Linked Data with PowerShell

Gets information stored in a page's [json-ld](https://json-ld.org/) (json linked data)

Many pages expose this information for search engine optimization.
Many pages expose this information for search engine optimization.

## JSON-LD in PowerShell
This module lets you easily get and work with JSON-LD objects.

JSON-LD is one of a number of ways you can get more information about a page.
## Installing and Importing

This information can be useful in any number of fun and useful PowerShell scenarios
You can install JSON-LD from the [PowerShell gallery](https://powershellgallery.com/)

For example, let's get information about a movie.
~~~PowerShell
Install-Module JSON-LD -Scope CurrentUser -Force
~~~

Once installed, you can import the module with:

~~~PowerShell
Get-JsonLD -Url https://letterboxd.com/film/amelie/
Import-Module JSON-LD -PassThru
~~~


You can also clone the repo and import the module locally:

~~~PowerShell
git clone https://github.com/PoshWeb/JSON-LD
cd ./JSON-LD
Import-Module ./ -PassThru
~~~

Let's take things a step further, and get the information we can know about any movie:
## Functions
JSON-LD has 1 function
### Get-JsonLD
#### Gets JSON-LD data from a given URL.
Gets JSON Linked Data from a given URL.

This is a format used by many websites to provide structured data about their content.
##### Examples
###### Example 1
Want to get information about a movie? Linked Data to the rescue!
~~~PowerShell
JsonLD https://schema.org/Movie
Get-JsonLD -Url https://letterboxd.com/film/amelie/
~~~

###### Example 2
Want information about an article? Lots of news sites use this format.
~~~PowerShell
Get-JsonLD https://www.thebulwark.com/p/mahmoud-khalil-immigration-detention-first-amendment-free-speech-rights
~~~
###### Example 3
Want to get information about a schema?
~~~PowerShell
jsonld https://schema.org/Movie
# Get-JSONLD will output the contents of a `@Graph` object if no `@type` is found.
~~~
##### Parameters

|Name|Type|Description|
|-|-|-|
|Url|Uri|The URL that may contain JSON-LD data|
|as|String|If set, will the output as:<br/><br/>|as|is|<br/>|-|-|<br/>|html|the response as text|<br/>|json|the match as json|<br/>|*jsonld`|ld`|linkedData*|the match as linked data|'<br/>|script|the script tag|<br/>|xml|the script tag, as xml||
|Force|SwitchParameter|If set, will force the request to be made even if the URL has already been cached.|

> (c) 2025-2026 Start-Automating.

> [LICENSE](https://github.com/PoshWeb/JSON-LD/blob/main/LICENSE)
Loading
Loading