How to import JSON into SQL 2016 - sql-server
I'm trying something new and could use some guidance. I have a JSON file full of data that I would like to have imported into SQL 2016. I can get the entire file into SQL but breaking it apart into a readable format is where I am stuck. I'm new to SQL, so when reading articles on this subject I am struggling to comprehend. The following query is what I've used to perform the initial import:
SELECT *
FROM OPENROWSET (BULK 'c:\tmp\test.json', SINGLE_CLOB) as j
CROSS APPLY OPENJSON(BulkColumn)
Each row is populated but the values contain sub sections that I need to have expanded. Here is the test data that I am using:
{
"site_id":123456,
"statusEnum":"fully_configured",
"status":"fully-configured",
"domain":"site.name.com",
"account_id":111111,
"acceleration_level":"standard",
"site_creation_date":1410815844000,
"ips":[
"99.99.99.99"
],
"dns":[
{
"dns_record_name":"site.name.com",
"set_type_to":"CNAME",
"set_data_to":[
"frgt.x.wafdns.net"
]
}
],
"original_dns":[
{
"dns_record_name":"name.com",
"set_type_to":"A",
"set_data_to":[
""
]
},
{
"dns_record_name":"site.name.com",
"set_type_to":"A",
"set_data_to":[
"99.99.99.99"
]
},
{
"dns_record_name":"site.name.com",
"set_type_to":"CNAME",
"set_data_to":[
""
]
}
],
"warnings":[
],
"active":"active",
"additionalErrors":[
],
"display_name":"site.name.com",
"security":{
"waf":{
"rules":[
{
"action":"api.threats.action.block_ip",
"action_text":"Block IP",
"id":"api.threats.sql_injection",
"name":"SQL Injection"
},
{
"action":"api.threats.action.block_request",
"action_text":"Block Request",
"id":"api.threats.cross_site_scripting",
"name":"Cross Site Scripting"
},
{
"action":"api.threats.action.block_ip",
"action_text":"Block IP",
"id":"api.threats.illegal_resource_access",
"name":"Illegal Resource Access"
},
{
"block_bad_bots":true,
"challenge_suspected_bots":true,
"exceptions":[
{
"values":[
{
"ips":[
"99.99.99.99"
],
"id":"api.rule_exception_type.client_ip",
"name":"IP"
}
],
"id":123456789
},
{
"values":[
{
"ips":[
"99.99.99.99"
],
"id":"api.rule_exception_type.client_ip",
"name":"IP"
}
],
"id":987654321
}
],
"id":"api.threats.bot_access_control",
"name":"Bot Access Control"
},
{
"activation_mode":"api.threats.ddos.activation_mode.auto",
"activation_mode_text":"Auto",
"ddos_traffic_threshold":1000,
"id":"api.threats.ddos",
"name":"DDoS"
},
{
"action":"api.threats.action.quarantine_url",
"action_text":"Auto-Quarantine",
"id":"api.threats.backdoor",
"name":"Backdoor Protect"
},
{
"action":"api.threats.action.block_ip",
"action_text":"Block IP",
"id":"api.threats.remote_file_inclusion",
"name":"Remote File Inclusion"
},
{
"action":"api.threats.action.disabled",
"action_text":"Ignore",
"id":"api.threats.customRule",
"name":"wafRules"
}
]
},
"acls":{
"rules":[
{
"ips":[
"99.99.99.99"
],
"id":"api.acl.whitelisted_ips",
"name":"Visitors from whitelisted IPs"
},
{
"geo":{
"countries":[
"BR",
"CN",
"DE",
"ES",
"GB",
"HK",
"IR",
"IT",
"KP",
"KR",
"KZ",
"NL",
"PL",
"RO",
"RU",
"TR",
"TW",
"UA"
]
},
"id":"api.acl.blacklisted_countries",
"name":"Visitors from blacklisted Countries"
}
]
}
},
"sealLocation":{
"id":"api.seal_location.none",
"name":"No seal "
},
"ssl":{
"origin_server":{
"detected":true,
"detectionStatus":"ok"
},
"generated_certificate":{
"ca":"GS",
"validation_method":"email",
"validation_data":"administrator#site.name.com",
"san":[
"*.site.name.com"
],
"validation_status":"done"
}
},
"siteDualFactorSettings":{
"specificUsers":[
],
"enabled":false,
"customAreas":[
],
"allowAllUsers":true,
"shouldSuggestApplicatons":true,
"allowedMedia":[
"ga",
"sms"
],
"shouldSendLoginNotifications":true,
"version":0
},
"login_protect":{
"enabled":false,
"specific_users_list":[
],
"send_lp_notifications":true,
"allow_all_users":true,
"authentication_methods":[
"ga",
"sms"
],
"urls":[
],
"url_patterns":[
]
},
"performance_configuration":{
"advanced_caching_rules":{
"never_cache_resources":[
],
"always_cache_resources":[
]
},
"acceleration_level":"standard",
"async_validation":true,
"minify_javascript":true,
"minify_css":true,
"minify_static_html":true,
"compress_jepg":true,
"progressive_image_rendering":false,
"aggressive_compression":false,
"compress_png":true,
"on_the_fly_compression":true,
"tcp_pre_pooling":true,
"comply_no_cache":false,
"comply_vary":false,
"use_shortest_caching":false,
"perfer_last_modified":false,
"accelerate_https":false,
"disable_client_side_caching":false,
"cache300x":false,
"cache_headers":[
]
},
"extended_ddos":1000,
"res":0,
"res_message":"OK",
"debug_info":{
"id-info":"1234"
}
}
I know enough about SQL to know that I am going to have to have multiple tables for these subsections. How do I select these subsections to expand them out into their own tables? If I am not clear on the explanation or the question, please comment and I will do my best to be more precise.
I was able to successfully import my JSON data into a SQL data base using the following code:
###Getting the list of Site_IDs
$param1 = #{account_id='####';api_id='######'; api_key='asdfjklmnopqrstuvwxyz';page_size='1000'}
$sitelist = Invoke-WebRequest https://my.website.com/api/prov/v1/sites/list -Method Post -Body $param1
$sitelist = $sitelist.content
$sitelist = $sitelist | convertfrom-json
$sitelist = $sitelist.sites
$sites = $sitelist | select -ExpandProperty Site_ID
###Setting the ConnectionString for the SQL Server and Database
$server = 'servername\sqlinstance'
$database = 'databasename'
$connstring = "server = $server; database = $database; trusted_connection = true;"
$conn = New-Object System.Data.SqlClient.SqlConnection
$conn.ConnectionString = $connstring
$cmd = New-Object System.Data.SqlClient.SqlCommand
$cmd.CommandTimeout = 60
$cmd.Connection = $conn
$cmd.CommandText = $query
$cmd.Parameters.Add((New-Object Data.SqlClient.SqlParameter("#Site_ID",[Data.SQLDBType]::BigInt,20))) | Out-Null
$cmd.Parameters.Add((New-Object Data.SqlClient.SqlParameter("#JSON_Source",[Data.SQLDBType]::NVARCHAR))) | Out-Null
###Setting the SQL Query to Insert the Site Data
$query = #"
INSERT INTO dbo.WebsiteSourceData (Site_ID,JSON_Source)
Values (#Site_ID, #JSON_Source);
"#
###Opening the SQL Connection
Try{
$conn.Open()
###Looping through each site to get it's configuration and then inserting that data to SQL
ForEach($site in $sites){
$param2 = #{api_id='#####';api_key='abcdefghijklmnopqrstuvwxyz';site_id="$site"}
$status = Invoke-WebRequest -URI https://my.website.com/api/prov/v1/sites/status -Method Post -Body $param2
$content = $status.Content
$adapter = New-Object System.Data.SqlClient.SqlDataAdapter
$adapter.SelectCommand = $cmd
$cmd.Parameters[0].Value = $site
$cmd.Parameters[1].Value = $content
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataset)
}#ForEach($site in $sites)
}#Try
Catch{
Write-Host "Exception thrown : $($error[0].exception.message)"
}#Catch
Finally{
$conn.Close()
}#Finally
From there, using the extremely helpful advice from this thread: How to shred JSON data from within a SQL database I was able to access and parse out the data into separate tables.
Related
Powershell JSON : How to retrieve specific key-value pair for all array items
I am trying to get the list of "enabled" features from featureset array from below JSON snippet with powershell. output expected : feature1, feature2, feature4 I tried this piece of code but I was only able to get to the specific index of the array, not all elements, also not able to put condition for "enable" = true : $output = foreach( $feature in $jsn.abc.comp1.featureset[0].psobject.Properties ) { [PSCustomObject]#{ featureName = $feature.Name featureValue = $feature.Value } } json: { "abc": { "comp1": { "id": "1308", "featureset":[ { "name": "feature1", "enable" : true, "ID": "0670FF495355878281174937" }, { "name": "feature2", "enable" : true, "ID": "0670FF495355878281174937" }, { "name": "feature3", "enable" : false, "ID": "0670FF495355878281174937" }, { "name": "feature4", "enable" : true, "ID": "0670FF495355878281174937" } ] } } }
Loop over the whole featureset array, use Where-Object to filter: $output = $jsn.abc.comp1.featureset |Where-Object enable -eq $true |ForEach-Object { $_.Name }
How to add objects to a blank array in a json file using powershell
here is my json body . { "source": 2, "revision": 3, "description": null, "triggers": [], "releaseNameFormat": "Release-$(rev:r)", "tags": [], "pipelineProcess": { "type": 1 }, "properties": { "DefinitionCreationSource": { "$type": "System.String", "$value": "BuildSummary" }, "System.EnvironmentRankLogicVersion": { "$type": "System.String", "$value": "2" } }, "id": 5, "name": "CheckListAPI - CD", "path": "\\Admin", "projectReference": null, "url": "", "_links": { "self": { "href": "" }, "web": { "href": "" } } } I want to add some values inside the brackets at "triggers": [], What I'm trying to get is: "triggers": [ { "artifactAlias": "_DV_NJ_PIPE", "triggerConditions": [], "triggerType": 1 } ], i tried -replace and replace() saving the json file to local system, but none of them are working, I even tried to edit the json file directly like this but failed. $alias = $json.triggers foreach ($artifact in $alias ) { $artifact.artifactAlias = "_$DefName" $artifact.triggerConditions = "{}" $artifact.triggertype = "artifactSource" } Please help.
You can import the json file as PowerShell objects, manipulate the structure until it looks the way you want it to and export it back to json format: $pipeline = Get-Content .\input.json | ConvertFrom-Json $trigger = [ordered]#{ artifactAlias = "_DV_NJ_PIPE" triggerConditions = #() triggerType = 1 } $pipeline.triggers += $trigger $pipeline | ConvertTo-Json -Depth 5 | Out-File .\output.json As it was pointed out in the comments, it is of course also possible to import the trigger definition from a json file instead of building it in a hash table.
Replace symbol in JSON with different array values
I have 2 files text.json that contains { "Files": [ { "pattern": "/Something/Something/*" }, { "pattern": "/Something/Something/*" }, { "pattern": "/Something/Something/*" }, { "pattern": "/Something/Something/*" }, { "pattern": "/Something/Something/*" }, { "pattern": "/Something/Something/*" } ] } and dlls.txt 1.dll 2.dll .. 6.dll I want to replace the symbol * with the necessary dll like this : "Files": [ { "pattern": "/Something/Something/1.dll" }, { "pattern": "/Something/Something/2.dll" }, . . . { "pattern": "/Something/Something/6.dll" } ] } So far my code replaces the symbol but only with the last array element.
Since you're dealing with a structured data format - JSON - using a dedicated parser is always preferable to performing purely textual processing based on regexes. While using the dedicated ConvertFrom-Json and ConvertTo-Json cmdlets to parse from and serialize back to JSON is slower than textual processing, it is much more robust. # Read the DLL names from the text file into an array of strings. $dlls = Get-Content dlls.txt # Read the JSON file and parse it into an object. $objFromJson = Get-Content -Raw text.json | ConvertFrom-Json # Loop over all elements of the array in the .Files property and # update their .pattern property based on the corresponding DLL names. $i = 0 $objFromJson.Files.ForEach({ $_.pattern = $_.pattern -replace '(?<=/)\*$', $dlls[$i++] }) # Convert the updated object back to JSON; save to a file as needed. $objFromJson | ConvertTo-Json
Why not skip the 'C:\Users\itsan\Desktop\text.json' file alltogether and simply create a new JSON from the dll filenames you have in 'C:\Users\itsan\Desktop\dlls.txt' ? $dlls = Get-Content -Path 'C:\Users\itsan\Desktop\dlls.txt' $result = [PsCustomObject]#{ Files = foreach($file in $dlls) { "" | Select-Object #{Name = 'pattern'; Expression = {"/Something/Something/$file"}} } } $result | ConvertTo-Json If you want that as new file, simply change the last line into $result | ConvertTo-Json | Set-Content -Path 'C:\Users\itsan\Desktop\dll.json' Output wil be like this: { "Files": [ { "pattern": "/Something/Something/1.dll" }, { "pattern": "/Something/Something/2.dll" }, { "pattern": "/Something/Something/3.dll" }, { "pattern": "/Something/Something/4.dll" }, { "pattern": "/Something/Something/5.dll" }, { "pattern": "/Something/Something/6.dll" } ] }
Laravel how to return object into JSON Arrays data type without keys
I have DB query in the Controller like this: $query = User::all('id','name','email')->take(2); $users = ["data" => $query]; return $users; And get the result: { "data": [ { "id": 1, "name": "Peter", "email": "peter#peter.com" }, { "id": 2, "name": "John", "email": "john#john.com" } ] } But i'm expecting to get JSON Arrays data type without keys like this: { "data": [ [ "1", "Peter", "peter#peter.com" ], [ "2", "John", "john#john.com" ] ] } I need to get this type for DataTables JSONP data source for remote domains. https://datatables.net/examples/server_side/jsonp.html How to do this? Thanks.
You can try array_values like so: $query = User::all('id', 'name', 'email')->take(2); $users = ["data" => $query->map(function (User $user) { return array_values($user->attributesToArray()); })]; return $users;
How about something like this? $query = User::all('id', 'name', 'email')->take(2); $userValues = $query->map(function($item, $key) { return [ $item['id'], $item['name'], $item['email'] ]; }) $users = ["data" => $userValues]; return $users; // result { "data": [ [ 1, "Amy Wilderman", "vrau#example.net", ], [ 2, "Bria Lindgren PhD", "trevor.armstrong#example.org", ], ] }
How to add an object in array on parsed JSON?
I have this file .json: { "topologyTypes": { "stations": { "instances": [ { "#name": "value1", "#address": "value2" }, { "#name": "value3", "#address": "value4" } ] } }, "agg": {}, "inter": {} } I want to add an object like this in topologyType.stations.instances with PowerShell { "#name": "value4", "#adress": "value5" } So I tried this following code in PowerShell, but it doesn't work: $path = "./data.json" $jsonFile = Get-Content $path -Raw | ConvertFrom-Json $jsonContent = #" { "#name": "value4", "#adress": "value5" } "# $jsonFile.topologyTypes.stations.instances | Add-Content -Value (ConvertFrom-Json $jsonContent) The desired output I would like to get is like this: { "topologyTypes": { "stations": { "instances": [ { "#name": "value1", "#address": "value2" }, { "#name": "value3", "#address": "value4" }, { "#name": "value4", "#address": "value5" } ] } }, "agg": {}, "inter": {} }
Define the new content as a PowerShell custom object: $jsonContent = [PSCustomObject]#{ '#name' = 'value4' '#adress' = 'value5' } append it to the instances substructure of your imported JSON data: $jsonFile.topologyTypes.stations.instances += $jsonContent then convert the data back to a JSON string: $jsonFile | ConvertTo-Json -Depth 4 Note that ConvertTo-Json inserts a lot of intention space. If you want exactly the format you posted you need to do some pretty-printing yourself. Something like this might help.