Quantcast
Channel: Hey, Scripting Guy! Blog
Viewing all articles
Browse latest Browse all 3333

JSON Is the New XML

$
0
0

Summary: June Blender provides a primer about JSON.

Honorary Scripting Guy, June Blender, here. Today I'm going to introduce you to JSON.

June is a writer for the Azure Active Directory SDK. She is also a frequent contributor to the Hey, Scripting Guy! Blog and for PowerShell.org. She lives in magnificent Escalante, Utah, where she works remotely when she's not out hiking, kayaking, or convincing lost tourists to try Windows PowerShell. She believes that outstanding documentation is a collaborative effort, and she welcomes your comments and contributions. Follow her on Twitter at @juneb_get_help. To read more by June, see these Hey, Scripting Guy! Blog posts

I've been having a lot of fun learning web programming and working in Microsoft Azure and Azure PowerShell. I've noticed that I'm encountering a lot more JSON and a lot less XML over time. So, I thought I'd give our beginners a little primer on JSON.

JavaScript Object Notation (JSON) is a "lightweight data-interchange format." It is a way for programs to talk to each other, which is easy for humans to read and write, and easy for machines to parse and generate. It's also really compressible. Unlike XML, which is wordy, you can squish JSON into a very few bytes so it's small enough to include in fields with character limits, like the headers in the HTTP requests that web programs use to communicate.

A JSON document is a string that looks like a hash table with name=value (or name:value) pairs, such as {"Color"="Purple"} and  {"State":"Utah"}. It allows nesting, such as the "address" element this Wikipedia example:

{

    "firstName": "John",

    "lastName": "Smith",

    "isAlive": true,

    "age": 25,

    "height_cm": 167.64,

    "address": {

        "streetAddress": "21 2nd Street",

        "city": "New York",

        "state": "NY",

        "postalCode": "10021-3100"

    }

}

JSON documents that are used for interprogram communication are based on a schema. The schemas are also written in JSON and are easy to interpret. You can use a JSON schema to determine how to write a JSON document, and then after writing, use it to validate a JSON document.

Fortunately, JSON is very easy to manage in Windows PowerShell. The ConvertFrom-Json cmdlet converts the JSON object into a custom object (PSCustomObject). JSON is case-sensitive, but the custom objects are case-insensitive.

To get a JSON string from a JSON file, use the Get-Content cmdlet with its Raw parameter. 

PS C:\> Get-Content -Raw -Path .\myJson.json

{

    "firstName": "John",

    "lastName": "Smith",

    "isAlive": true,

    "age": 25,

    "height_cm": 167.64,

    "address": {

        "streetAddress": "21 2nd Street",

        "city": "New York",

        "state": "NY",

        "postalCode": "10021-3100"

    }

}

To convert it to a custom object, pipe the JSON string to the ConvertFrom-Json cmdlet:

PS C:\> $j = Get-Content -Raw -Path .\myJson.json | ConvertFrom-Json

PS C:\> $j

firstName : John

lastName  : Smith

isAlive   : True

age       : 25

height_cm : 167.64

address   : @{streetAddress=21 2nd Street; city=New York; state=NY; postalCode=10021-3100}

PS C:\> $j.address

streetAddress     city       state      postalCode

-------------     ----       -----      ----------

21 2nd Street     New York   NY         10021-3100

The Raw parameter tells Get-Content to ignore line breaks and return a single string. You can tell how many strings you have by counting the number of objects that are returned. Without Raw, you get 13 separate strings. With Raw, you get a single string.

PS C:\> (Get-Content -Path .\myJson.json).count

13

PS C:\> (Get-Content -Path .\myJson.json -Raw).count

1

If you forget the Raw parameter and pipe multiple strings to ConvertFrom-Json, you get this distinctive error message, which is Pig Latin for "Did you forget the Raw parameter?"

ConvertFrom-Json : Invalid object passed in, ':' or '}' expected. (1): {

At line:1 char:20

+ cat .\myJson.json | ConvertFrom-Json

+                    ~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [ConvertFrom-Json], ArgumentException

    + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand

The ConvertFrom-Json cmdlet converts each JSON string into a custom object. It converts each name-value pair into a note property and its value.

PS C:\> $j = Get-Content -Raw -Path .\myJson.json | ConvertFrom-Json

PS C:\> $j | Get-Member

   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition

----        ----------   ----------

Equals      Method       bool Equals(System.Object obj)

GetHashCode Method       int GetHashCode()

GetType     Method       type GetType()

ToString    Method       string ToString()

address     NoteProperty System.Management.Automation.PSCustomObject

age         NoteProperty System.Int32 age=25

firstName   NoteProperty System.String firstName=John

height_cm   NoteProperty System.Decimal height_cm=167.64

isAlive     NoteProperty System.Boolean isAlive=True

lastName    NoteProperty System.String lastName=Smith

For example, it converts this:

"firstName": "John"

…into a firstName note property with a value of John:

PS C:\> $j.firstName

John

When it encounters a nested JSON object, like the one in the value of address, it converts the value into a nested custom object with note properties representing each name-value pair.

For example, it converts this:

"address":  {

                    "streetAddress":  "21 2nd Street",

                    "city":  "New York",

                    "state":  "NY",

                    "postalCode":  "10021-3100"

                }

To:

PS C:\> $j.address

streetAddress     city       state      postalCode

-------------     ----       -----      ----------

21 2nd Street     New York   NY         10021-3100

…which is a custom object with its own note properties:

PS C:\> $j.address | Get-Member

   TypeName: System.Management.Automation.PSCustomObject

Name          MemberType   Definition

----          ----------   ----------

Equals        Method       bool Equals(System.Object obj)

GetHashCode   Method       int GetHashCode()

GetType       Method       type GetType()

ToString      Method       string ToString()

city          NoteProperty System.String city=New York

postalCode    NoteProperty System.String postalCode=10021-3100

state         NoteProperty System.String state=NY

streetAddress NoteProperty System.String streetAddress=21 2nd Street

You can edit the custom object and then use the ConvertTo-Json cmdlet and Set-Content cmdlets to replace the value in the .json file. Let's move John Smith to a more scenic location:

$j.address.city = "Escalante"

$j.address.state = "UT"

$j.address.postalCode = "84726"

 

PS C:\> $j

firstName : John

lastName  : Smith

isAlive   : True

age       : 25

height_cm : 167.64

address   : @{streetAddress=21 2nd Street; city=Escalante; state=UT; postalCode=84726}

Now, convert the custom object back to JSON...

PS C:\> $j | ConvertTo-Json

{

    "firstName":  "John",

    "lastName":  "Smith",

    "isAlive":  true,

    "age":  25,

    "height_cm":  167.64,

    "address":  {

                    "streetAddress":  "21 2nd Street",

                    "city":  "Escalante",

                    "state":  "UT",

                    "postalCode":  "84726"

                }

}

…and replace the content in the myJson.json file:

PS C:\> $j | ConvertTo-Json | Set-Content -Path .\myJson.json

Now you're ready to work with more complex JSON strings, such as the new Azure Gallery templates. More on that subject in another post.

I invite you to follow the Scripting Guys on Twitter and Facebook. If you have any questions, send email to scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum

June Blender, senior programming writer and Microsoft Scripting Guy


Viewing all articles
Browse latest Browse all 3333

Trending Articles