Reputation: 35
I am getting JSON data after consuming an API in my stored procedure. I am trying to parse this JSON but while trying to parse it, I get an error
JSON path is not properly formatted. Unexpected character '@' is found at position 2
I was wondering how can I pass this @variant_description
dynamic variable to my parser?
Thank you in advance
ALTER PROCEDURE [dbo].[usp_CallAPI]
@genome_build nvarchar(50),
@variant_description nvarchar(50),
@select_transcripts nvarchar(50)
AS
BEGIN
DECLARE @Object AS Int;
DECLARE @hr int, @APIfunction nvarchar(max)
DECLARE @json AS TABLE (Json_Table nvarchar(max))
DECLARE @Json_response AS nvarchar(max)
SET @APIfunction = 'https://rest.variantvalidator.org/VariantValidator/variantvalidator/'+ @genome_build+'/'+@variant_description+'/'+@select_transcripts
EXEC @hr = sp_OACreate 'MSXML2.ServerXMLHTTP.6.0', @Object OUT;
IF @hr <> 0
EXEC sp_OAGetErrorInfo @Object
EXEC @hr = sp_OAMethod @Object, 'open', NULL, 'get', @APIfunction
, --Your Web Service Url (invoked)
'false'
IF @hr <> 0
EXEC sp_OAGetErrorInfo @Object
EXEC @hr = sp_OAMethod @Object, 'send'
IF @hr <> 0
EXEC sp_OAGetErrorInfo @Object
EXEC @hr = sp_OAMethod @Object, 'responseText', @json OUTPUT
IF @hr <> 0
EXEC sp_OAGetErrorInfo @Object
INSERT INTO @json (Json_Table)
EXEC sp_OAGetProperty @Object, 'responseText'
-- select the JSON string
-- SELECT '"elements": ['+Json_Table+ ']' FROM @json
-- SELECT * FROM @json
-- Parse the JSON string
SELECT *
FROM OPENJSON((SELECT CONCAT('{', QUOTENAME('elements', '"'), ':['+Json_Table+ ']}') FROM @json), N'$.elements')
WITH (
-- [seqrepo_db] nvarchar(max) N'$.seqrepo_db' ,
[variant_description] nvarchar(max) N'$.@variant_description' AS JSON,
[flag] nvarchar(max) N'$.flag',
[metadata] nvarchar(max) N'$.metadata' AS JSON
)
EXEC sp_OADestroy @Object
END
For example, I want to execute the following
EXEC [dbo].usp_CallAPI @genome_build ='GRCh37',@variant_description = 'NM_000088.3:c.589G>T', @select_transcripts ='all';
For example, this is the test JSON which I am getting back from the API request
{
"NM_000088.3:c.589G>T": {
"alt_genomic_loci": [],
"gene_ids": {
"ccds_ids": [
"CCDS11561"
],
"ensembl_gene_id": "ENSG00000108821",
"entrez_gene_id": "1277",
"hgnc_id": "HGNC:2197",
"omim_id": [
"120150"
],
"ucsc_id": "uc002iqm.4"
},
"gene_symbol": "COL1A1",
"genome_context_intronic_sequence": "",
"hgvs_lrg_transcript_variant": "LRG_1t1:c.589G>T",
"hgvs_lrg_variant": "LRG_1:g.8638G>T",
"hgvs_predicted_protein_consequence": {
"slr": "NP_000079.2:p.(G197C)",
"tlr": "NP_000079.2(LRG_1p1):p.(Gly197Cys)"
},
"hgvs_refseqgene_variant": "NG_007400.1:g.8638G>T",
"hgvs_transcript_variant": "NM_000088.3:c.589G>T",
"primary_assembly_loci": {
"grch37": {
"hgvs_genomic_description": "NC_000017.10:g.48275363C>A",
"vcf": {
"alt": "A",
"chr": "17",
"pos": "48275363",
"ref": "C"
}
},
"grch38": {
"hgvs_genomic_description": "NC_000017.11:g.50198002C>A",
"vcf": {
"alt": "A",
"chr": "17",
"pos": "50198002",
"ref": "C"
}
},
"hg19": {
"hgvs_genomic_description": "NC_000017.10:g.48275363C>A",
"vcf": {
"alt": "A",
"chr": "chr17",
"pos": "48275363",
"ref": "C"
}
},
"hg38": {
"hgvs_genomic_description": "NC_000017.11:g.50198002C>A",
"vcf": {
"alt": "A",
"chr": "chr17",
"pos": "50198002",
"ref": "C"
}
}
},
"reference_sequence_records": {
"lrg": "http://ftp.ebi.ac.uk/pub/databases/lrgex/LRG_1.xml",
"protein": "https://www.ncbi.nlm.nih.gov/nuccore/NP_000079.2",
"refseqgene": "https://www.ncbi.nlm.nih.gov/nuccore/NG_007400.1",
"transcript": "https://www.ncbi.nlm.nih.gov/nuccore/NM_000088.3"
},
"refseqgene_context_intronic_sequence": "",
"submitted_variant": "NM_000088.3:c.589G>T",
"transcript_description": "Homo sapiens collagen type I alpha 1 chain (COL1A1), mRNA",
"validation_warnings": []
},
"flag": "gene_variant",
"metadata": {
"seqrepo_db": "2018-08-21",
"uta_schema": "uta_20180821",
"variantvalidator_hgvs_version": "1.2.5.vv1",
"variantvalidator_version": "1.0.4.dev17+gd16b9ef.d20200422"
}
}
Upvotes: 2
Views: 2398
Reputation: 29983
I don't think that you can use a variable for a path
expression, when you use OPENJSON()
and explicit schema (the WITH
clause). But, if the JSON response has a fixed structure - a JSON object (not array) with three key\value
pairs (first with a variable name, "flag"
and "metadata"
), you may try to change the way you are parsing the JSON and use JSON_VALUE()
and JSON_QUERY()
. In this case, starting from SQL Server 2017, you can provide a variable as the value of path
. Also, you do not need to build a new JSON object ({"elements:[...]"}
), simply parse the returned JSON response.
Use the following statement at the end of your stored procedure:
SELECT
variant_description = JSON_QUERY(@json, '$."' + @variant_description + '"'),
flag = JSON_VALUE(@json, '$."flag"'),
metadata = JSON_QUERY(@json, '$."metadata"')
instead of:
SELECT *
FROM OPENJSON(
(SELECT CONCAT('{', QUOTENAME('elements', '"'), ':['+Json_Table+ ']}') FROM @json),
N'$.elements'
) WITH (
-- [seqrepo_db] nvarchar(max) N'$.seqrepo_db' ,
[variant_description] nvarchar(max) N'$.@variant_description' AS JSON,
[flag] nvarchar(max) N'$.flag',
[metadata] nvarchar(max) N'$.metadata' AS JSON
)
As a side note (and for your future work), the actual reason for the "JSON path is not properly formatted. Unexpected character '@' is found at position 2" error is the fact, that you use N'$.@variant_description'
as a path expression
. As is explained in the documentation, if ... the key name starts with a dollar sign or contains special characters such as spaces, surround it with quotes (e.g. N'$."@variant_description"'
).
Upvotes: 1