I have the following table:
CREATE TABLE [dbo].[PRC_Tutors]
(
[ID] [int] NOT NULL,
[UserID] [int] NOT NULL,
[LivelloZoom] [int] NULL,
[PosizioneGIS] [nvarchar](max) NULL,
CONSTRAINT [PK_PRC_Tutors]
PRIMARY KEY CLUSTERED ([ID] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
This is the insert query:
INSERT INTO [dbo].[PRC_Tutors] ([ID], [UserID], [LivelloZoom], [PosizioneGIS])
VALUES (1, 1, 18, 'POLYGON((10.932815861897701 45.598233964590946,11.138809514241451 44.993985917715946,12.270401311116451 44.969266679434696,12.152298283772701 45.529569413809696,10.932815861897701 45.598233964590946))')
INSERT INTO [dbo].[PRC_Tutors] ([ID], [UserID], [LivelloZoom], [PosizioneGIS])
VALUES (2, 100, 10, 'POLYGON((12.053217932309531 44.2095244414735,12.261958166684531 44.14085989069225,12.341609045590781 44.280935574286,12.168574377622031 44.42650442194225,12.053217932309531 44.2095244414735))')
This is my query that returns a JSON:
SELECT
CAST((SELECT
'OK' As [status],
TU.livelloZoom AS livelloZoom,
(SELECT REPLACE(REPLACE(N.PosizioneGIS, 'POLYGON((',''), '))', '') AS area
FROM AA_V_PRC_Tutors N
WHERE N.ID = TU.ID
FOR JSON PATH, INCLUDE_NULL_VALUES) AS area
FROM
AA_V_PRC_Tutors TU
WHERE
UserID = @User_id
FOR JSON PATH, INCLUDE_NULL_VALUES, WITHOUT_ARRAY_WRAPPER) AS nvarchar(max))
This is the JSON output of this query:
{
"status":"OK",
"livelloZoom":18,
"area":[
{"area":"10.932815861897701 45.598233964590946,
11.138809514241451 44.993985917715946,
12.270401311116451 44.969266679434696,
12.152298283772701 45.529569413809696,
10.932815861897701 45.598233964590946"
}
]
}
But I need to generate the following JSON:
{
"status":"OK",
"livelloZoom":18,
"area":[
[10.932815861897701, 45.598233964590946],
[11.138809514241451, 44.993985917715946],
[12.270401311116451, 44.969266679434696],
[12.152298283772701, 45.529569413809696],
[10.932815861897701, 45.598233964590946]
]
}
How can I get that JSON?
2
Answers
Firstly, you don’t need the
AA_V_PRC_Tutors N
reference, you can refer to the outer columns directly. You also don’t need th conversion tonvarchar(max)
as that the default output ofFOR JSON
.SQL Server unfortunately doesn’t support
JSON_AGG
yet, which means we need to hack it withSTRING_AGG
and then prevent double-escaping usingJSON_QUERY
.So, to get your result, we need to convert your data to the actual
geometry
type (not sure why it wasn’t in the first place), then useSTPointN
to get each point. So we also needGENERATE_SERIES
andSTNumPoints
to generate enough artifical rows.db<>fiddle
Given that you are using SQL Server 2016, you don’t have
STRING_AGG
so we need to use the oldFOR XML PATH('')
hack. And you don’t haveGENERATE_SERIES
so we need to use Itzik Ben-Gan’s cross-join generator.db<>fiddle
There are a few approaches to this problem:
REPLACE()
and nestedSTRING_SPLIT()
operations and then rebuild them up into JSON arrays.REPLACE()
to directly convert the WKT into a JSON nested array syntax and include it in the results usingJSON_QUERY()
.The below uses the third technique. The limitation is that the original data must precisely follow the expected format – no extra spaces or other variations.
Sample Result (formatted using jsonformatter.org):
See this db<>fiddle.