Posted at

ConvertFrom-Json for PowerShell v2

More than 1 year has passed since last update.

必要になったので書きました。1

Crockford 先生(?)のパーサ を PowerShell で書き直しただけです。reviver と一部のエラーチェックはサボっています。

Function ConvertFrom-Json {

param(
[Parameter(ValueFromPipeline=$True)]
[string[]]$InputObject
)
begin {
$buf = New-Object System.Text.StringBuilder
}
process {
foreach($b in $InputObject){
$buf.Append($b) > $null
}
}
end {
$ErrorActionPreference = "Stop"
$script:json = $buf.ToString()
$script:at = 0
$script:ch = " "
$script:escape = New-Object psobject |
Add-Member -PassThru NoteProperty '"' '"' |
Add-Member -PassThru NoteProperty "\" "\" |
Add-Member -PassThru NoteProperty "/" "/" |
Add-Member -PassThru NoteProperty "b" "`b" |
Add-Member -PassThru NoteProperty "f" "`f" |
Add-Member -PassThru NoteProperty "n" "`n" |
Add-Member -PassThru NoteProperty "r" "`r" |
Add-Member -PassThru NoteProperty "t" "`t"
$script:err = {
param($m)
throw "Syntax Error: $m, $at, $json"
}
$script:next = {
param($c)
if ($c -and $c -ne $ch) { & $err "Expected '$c' instead of '$ch'" }
$script:ch = $json[$at]
$script:at += 1
}
$script:number = {
$str = ""
$e = ""
if ($ch -eq "-") {
$str = "-"
& $next "-"
}
while($ch -ge "0" -and $ch -le "9") {
$str += $ch
& $next
}
if ($ch -eq "."){
$str += "."
& $next
while($ch -ge "0" -and $ch -le "9") {
$str += $ch
& $next
}
}
if ($ch -eq "e") {
& $next "e" # skip e
if ($ch -eq "+" -or $ch -eq "-") {
$e += $ch
& $next
}
while($ch -ge "0" -and $ch -le "9") {
$e += $ch
& $next
}
}
$number = [double]$str
if ($e) { $number *= [Math]::Pow(10, [int]$e) }
if ($number) {
return $number
} else {
& $err "Bad Number"
}
}
$script:string = {
$str = ""
if ($ch -eq '"') {
& $next
while($ch){
if($ch -eq '"') {
& $next
return $str
} elseif ($ch -eq "\") {
& $next
if ($ch -eq "u") {
$uffff = 0
1..4 | ForEach-Object {
& $next
$hex = [Convert]::ToInt32($ch, 16)
$uffff = $uffff * 16 + $hex
}
$str += [char]::ConvertFromUtf32($uffff)
} elseif ($escape.$ch){
$str += $escape.$ch
} else {
break
}
} else {
$str += $ch
}
& $next
}
}
& $err "Bad String"
}
$script:white = {
while($ch -and $ch -le " ") {
& $next
}
}
$script:word = {
switch($ch){
"t" {
& $next "t"
& $next "r"
& $next "u"
& $next "e"
return $true
}
"f" {
& $next "f"
& $next "a"
& $next "l"
& $next "s"
& $next "e"
return $false
}
"n" {
& $next "n"
& $next "u"
& $next "l"
& $next "l"
return $null
}
default {
& $err "Unexpected '$ch'"
}
}
}
$script:array = {
$arr = @()
if ($ch -eq "[") {
& $next "["
& $white
if ($ch -eq "]"){
& $next "]"
return $arr
}
while($ch) {
$arr += & $value
& $white
if ($ch -eq "]") {
& $next "]"
return $arr
}
& $next ","
& $white
}
}
& $err "Bad Array"
}
$script:object = {
$obj = New-Object PSObject
if ($ch -eq "{"){
& $next "{"
& $white
if ($ch -eq "}") {
& $next "}"
return $obj
}
while($ch){
$key = & $string
& $white
& $next ":"
$obj | Add-Member NoteProperty $key (& $value) # error if duplicate key
& $white
if ($ch -eq "}") {
& $next "}"
return $obj
}
& $next ","
& $white
}
}
& $err "Bad Object"
}
$script:value = {
& $white
switch($ch){
"{" { return & $object }
"[" { return & $array }
'"' { return & $string }
"-" { return & $number }
default {
if ($ch -ge "0" -and $ch -le "9") {
return & $number
} else {
return & $word
}
}
}
}
$result = & $value
& $white
if ($ch) {
& $err "Syntax Error"
}
return $result
}
}





  1. Windows7 と Windows Server 2008 早く消え去って欲しい