Forum Discussion

hohohono's avatar
hohohono
Brass Contributor
Aug 06, 2024

Easy HashTable Question

I'm tragically stuck on what I know is a simple query. 

 

For context, I'm trying to update a Bookings calendar service business hours through PowerShell.

The cmdlet is Update-MgBookingBusinessService.

The relevant JSON that is returned from Get-MgBookingBusinessService is below.

 

 

"schedulingPolicy": {
 "generalAvailability": {
  "availabilityType": "customWeeklyHours",
  "businessHours": [
   {
    "day": "monday",
    "timeSlots": [
     {
      "startTime": "10:30:00.0000000",
      "endTime": "18:30:00.0000000"
     }
    ]
   },
   {
    "day": "tuesday",
    "timeSlots": [
     {
      "startTime": "10:30:00.0000000",
      "endTime": "18:30:00.0000000"
     }
    ]
   },
   {
    "day": "wednesday",
    "timeSlots": [
     {
      "startTime": "10:30:00.0000000",
      "endTime": "18:30:00.0000000"
     }
    ]
   },
   {
    "day": "thursday",
    "timeSlots": [
     {
      "startTime": "10:30:00.0000000",
      "endTime": "18:30:00.0000000"
     }
    ]
   },
   {
    "day": "friday",
    "timeSlots": [
     {
      "startTime": "10:30:00.0000000",
      "endTime": "18:30:00.0000000"
     }
    ]
   },
   {
    "day": "saturday",
    "timeSlots": []
   },
   {
    "day": "sunday",
    "timeSlots": []
   }
  ]
 }
}

 

 

I know how to update the availabilityType:

Update-MgBookingBusinessService -BookingBusinessId <calendar> -BookingServiceId <service> -SchedulingPolicy @{"GeneralAvailability" = @{"availabilityType"="customWeeklyHours"}}

 

But the amount of nested arrays to update the startTime and endTime for timeSlots has left me braindead. I feel like I'm so close, but somehow I'm just not getting it, and I've given up. Could someone please light the way for me? Thank you!

  • hohohono 

     

    Hi, Carol.

     

    Here's some basic examples on how you can work with JSON in PowerShell.

     

    I've slightly adjusted your JSON example above as is was missing some curly braces and saved this into a local file for ease of use.

     

    Example JSON

     

    {
    "schedulingPolicy": {
     "generalAvailability": {
      "availabilityType": "customWeeklyHours",
      "businessHours": [
       {
        "day": "monday",
        "timeSlots": [
         {
          "startTime": "10:30:00.0000000",
          "endTime": "18:30:00.0000000"
         }
        ]
       },
       {
        "day": "tuesday",
        "timeSlots": [
         {
          "startTime": "10:30:00.0000000",
          "endTime": "18:30:00.0000000"
         }
        ]
       },
       {
        "day": "wednesday",
        "timeSlots": [
         {
          "startTime": "10:30:00.0000000",
          "endTime": "18:30:00.0000000"
         }
        ]
       },
       {
        "day": "thursday",
        "timeSlots": [
         {
          "startTime": "10:30:00.0000000",
          "endTime": "18:30:00.0000000"
         }
        ]
       },
       {
        "day": "friday",
        "timeSlots": [
         {
          "startTime": "10:30:00.0000000",
          "endTime": "18:30:00.0000000"
         }
        ]
       },
       {
        "day": "saturday",
        "timeSlots": []
       },
       {
        "day": "sunday",
        "timeSlots": []
       }
      ]
     }
    }
    }

     

     

    PowerShell doesn't work "natively" with JSON string data, so in order to make progress, we need to get it into a usable object, which we can do easily enough in one line:

     

    Read the JSON data from file into a local variable

     

    $Data = ConvertFrom-Json -InputObject (Get-Content -Path "D:\Data\Temp\Forum\forum.txt" -Raw);

     

     

    The "-Raw" tells Get-Content that we want a single, large string back, not the default which is an array of strings.

     

    Now that we have our object, we can navigate down the child attributes to get to the one we want: "startTime. If you're not sure what the next child object is named, that's okay as you can - in simple scenarios like this one - quickly "walk the object tree" as shown in the example below, where I'm simply adding the next attribute name of interest to the previous command:

     

    Walking a simple object tree

     

    Eventually, you'll drill down to what you want to see, which are the time values held in "timeSlots":

     

     

    And now we can code the changes to startTime and endTime. There's numerous ways you can handle this part, but I'm going to keep it deliberately simple and just use strings of the same format as from the original JSON.

     

    Changing startTime and endTime

     

    $Data.schedulingPolicy.generalAvailability.businessHours.timeSlots.ForEach({
        $_.startTime = "08:30:00.0000000";
        $_.endTime = "17:00:00.0000000";
    });

     

     

    Post-update verification

     

     

    At this point, we now have our updated object. Unfortunately, I cannot go further as I have nothing to run Update-MgBookingBusinessService against, but conceptually, it'd be a simple command.

     

    Using the example from your original post, it'd look like this:

     

    Calling Update-MgBookingBusinessService

     

    Update-MgBookingBusinessService -BookingBusinessId <calendar> -BookingServiceId <service> -SchedulingPolicy $Data;

     

     

     

    Putting it all together

     

    # Read the JSON data from the source file.
    $Data = ConvertFrom-Json -InputObject (Get-Content -Path "D:\Data\Temp\Forum\forum.txt" -Raw);
    
    # Change the times for all days.
    $Data.schedulingPolicy.generalAvailability.businessHours.timeSlots.ForEach({
        $_.startTime = "08:30:00.0000000";
        $_.endTime = "17:00:00.0000000";
    });
    
    # Update.
    Update-MgBookingBusinessService -BookingBusinessId "<calendar>" -BookingServiceId "<service>" -SchedulingPolicy $Data;

     

     

    Again, this is a simple explanation and examples where the main purpose is to illustrate how you can work with JSON. Hopefully it helps you formulate the precise solution you're looking for.

     

    And if the Update-MgBookingBusinessService call does not work, drop the error back in here so we can take a look at it. It probably won't be complex, but am not in a position to test this one, meaning I can't proof the above example end-to-end.

     

    Cheers,

    Lain

  • You can simply use a raw HTTPS request and pass the JSON without having to bother with hash tables. Use the Invoke-MgGraphRequest cmdlet for that (-Method PATCH -Body $jsonvariable).
    • hohohono's avatar
      hohohono
      Brass Contributor

      Wow, I didn't know this was an option! Super useful, thanks for sharing.

      Unfortunately, you'll have to spell it out for me even further. The root issue is that I'm getting confused by the deeply nested arrays (and my PS scripting skill is weak). I don't know how to use the Invoke-MgGraphRequest cmdlet to update the startTime and endTime. For my specific example, what would go in $jsonvariable? 

       

      EDIT: Hmm after a closer look, I think I understand this. I'll take a stab at it once I'm back on a Windows computer...

      (But I'm also still interested to know the answer to my initial question! What am I doing wrong to not get that hashtable right?!)

      • LainRobertson's avatar
        LainRobertson
        Silver Contributor

        hohohono 

         

        Hi, Carol.

         

        Here's some basic examples on how you can work with JSON in PowerShell.

         

        I've slightly adjusted your JSON example above as is was missing some curly braces and saved this into a local file for ease of use.

         

        Example JSON

         

        {
        "schedulingPolicy": {
         "generalAvailability": {
          "availabilityType": "customWeeklyHours",
          "businessHours": [
           {
            "day": "monday",
            "timeSlots": [
             {
              "startTime": "10:30:00.0000000",
              "endTime": "18:30:00.0000000"
             }
            ]
           },
           {
            "day": "tuesday",
            "timeSlots": [
             {
              "startTime": "10:30:00.0000000",
              "endTime": "18:30:00.0000000"
             }
            ]
           },
           {
            "day": "wednesday",
            "timeSlots": [
             {
              "startTime": "10:30:00.0000000",
              "endTime": "18:30:00.0000000"
             }
            ]
           },
           {
            "day": "thursday",
            "timeSlots": [
             {
              "startTime": "10:30:00.0000000",
              "endTime": "18:30:00.0000000"
             }
            ]
           },
           {
            "day": "friday",
            "timeSlots": [
             {
              "startTime": "10:30:00.0000000",
              "endTime": "18:30:00.0000000"
             }
            ]
           },
           {
            "day": "saturday",
            "timeSlots": []
           },
           {
            "day": "sunday",
            "timeSlots": []
           }
          ]
         }
        }
        }

         

         

        PowerShell doesn't work "natively" with JSON string data, so in order to make progress, we need to get it into a usable object, which we can do easily enough in one line:

         

        Read the JSON data from file into a local variable

         

        $Data = ConvertFrom-Json -InputObject (Get-Content -Path "D:\Data\Temp\Forum\forum.txt" -Raw);

         

         

        The "-Raw" tells Get-Content that we want a single, large string back, not the default which is an array of strings.

         

        Now that we have our object, we can navigate down the child attributes to get to the one we want: "startTime. If you're not sure what the next child object is named, that's okay as you can - in simple scenarios like this one - quickly "walk the object tree" as shown in the example below, where I'm simply adding the next attribute name of interest to the previous command:

         

        Walking a simple object tree

         

        Eventually, you'll drill down to what you want to see, which are the time values held in "timeSlots":

         

         

        And now we can code the changes to startTime and endTime. There's numerous ways you can handle this part, but I'm going to keep it deliberately simple and just use strings of the same format as from the original JSON.

         

        Changing startTime and endTime

         

        $Data.schedulingPolicy.generalAvailability.businessHours.timeSlots.ForEach({
            $_.startTime = "08:30:00.0000000";
            $_.endTime = "17:00:00.0000000";
        });

         

         

        Post-update verification

         

         

        At this point, we now have our updated object. Unfortunately, I cannot go further as I have nothing to run Update-MgBookingBusinessService against, but conceptually, it'd be a simple command.

         

        Using the example from your original post, it'd look like this:

         

        Calling Update-MgBookingBusinessService

         

        Update-MgBookingBusinessService -BookingBusinessId <calendar> -BookingServiceId <service> -SchedulingPolicy $Data;

         

         

         

        Putting it all together

         

        # Read the JSON data from the source file.
        $Data = ConvertFrom-Json -InputObject (Get-Content -Path "D:\Data\Temp\Forum\forum.txt" -Raw);
        
        # Change the times for all days.
        $Data.schedulingPolicy.generalAvailability.businessHours.timeSlots.ForEach({
            $_.startTime = "08:30:00.0000000";
            $_.endTime = "17:00:00.0000000";
        });
        
        # Update.
        Update-MgBookingBusinessService -BookingBusinessId "<calendar>" -BookingServiceId "<service>" -SchedulingPolicy $Data;

         

         

        Again, this is a simple explanation and examples where the main purpose is to illustrate how you can work with JSON. Hopefully it helps you formulate the precise solution you're looking for.

         

        And if the Update-MgBookingBusinessService call does not work, drop the error back in here so we can take a look at it. It probably won't be complex, but am not in a position to test this one, meaning I can't proof the above example end-to-end.

         

        Cheers,

        Lain

Resources