SQL解析Json

2021/6/26 20:01:25

本文主要是介绍SQL解析Json,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

  1 CREATE FUNCTION [dbo].[parseJSON] (@Json NVARCHAR(MAX))  
  2 RETURNS @hierarchy TABLE (element_id INT IDENTITY(1, 1) NOT NULL, /* internal surrogate primary key gives the order of parsing and the list order */  
  3                           sequenceNo [INT] NULL, /* the place in the sequence for the element */  
  4                           parent_ID INT, /* if the element has a parent then it is in this column. The document is the ultimate parent, so you can get the structure from recursing from the document */  
  5                           Object_ID INT, /* each list or object has an object id. This ties all elements to a parent. Lists are treated as objects here */  
  6                           NAME NVARCHAR(2000), /* the name of the object */  
  7                           StringValue NVARCHAR(MAX) NOT NULL, /*the string representation of the value of the element. */  
  8                           ValueType VARCHAR(10) NOT NULL /* the declared type of the value represented as a string in StringValue*/  
  9 )  
 10 AS  
 11 BEGIN  
 12   
 13     DECLARE @FirstObject            INT, --the index of the first open bracket found in the JSON string  
 14             @OpenDelimiter          INT, --the index of the next open bracket found in the JSON string  
 15             @NextOpenDelimiter      INT, --the index of subsequent open bracket found in the JSON string  
 16             @NextCloseDelimiter     INT, --the index of subsequent close bracket found in the JSON string  
 17             @Type                   NVARCHAR(10), --whether it denotes an object or an array  
 18             @NextCloseDelimiterChar CHAR(1), --either a '}' or a ']'  
 19             @Contents               NVARCHAR(MAX), --the unparsed contents of the bracketed expression  
 20             @Start                  INT, --index of the start of the token that you are parsing  
 21             @end                    INT, --index of the end of the token that you are parsing  
 22             @param                  INT, --the parameter at the end of the next Object/Array token  
 23             @EndOfName              INT, --the index of the start of the parameter at end of Object/Array token  
 24             @token                  NVARCHAR(200), --either a string or object  
 25             @value                  NVARCHAR(MAX), -- the value as a string  
 26             @SequenceNo             INT, -- the sequence number within a list  
 27             @name                   NVARCHAR(200), --the name as a string  
 28             @parent_ID              INT, --the next parent ID to allocate  
 29             @lenJSON                INT, --the current length of the JSON String  
 30             @characters             NCHAR(36), --used to convert hex to decimal  
 31             @result                 BIGINT, --the value of the hex symbol being parsed  
 32             @index                  SMALLINT, --used for parsing the hex value  
 33             @Escape                 INT; --the index of the next escape character  
 34     DECLARE @Strings TABLE /* in this temporary table we keep all strings, even the names of the elements, since they are 'escaped' in a different way, and may contain, unescaped, brackets denoting objects or lists. These are replaced in the JSON string b
 35 y tokens representing the string */  
 36     (String_ID INT IDENTITY(1, 1),  
 37      StringValue NVARCHAR(MAX));  
 38     SELECT --initialise the characters to convert hex to ascii  
 39         @characters = N'0123456789abcdefghijklmnopqrstuvwxyz',  
 40         @SequenceNo = 0, --set the sequence no. to something sensible.  
 41         @parent_ID = 0;  
 42     WHILE 1 = 1 --forever until there is nothing more to do  
 43     BEGIN  
 44         SELECT @Start = PATINDEX('%[^a-zA-Z]["]%', @Json COLLATE SQL_Latin1_General_CP850_BIN); --next delimited string  
 45         IF @Start = 0  
 46             BREAK; --no more so drop through the WHILE loop  
 47         IF SUBSTRING(@Json, @Start + 1, 1) = '"'  
 48         BEGIN --Delimited Name  
 49             SET @Start = @Start + 1;  
 50             SET @end = PATINDEX('%[^\]["]%', RIGHT(@Json, LEN(@Json + '|') - @Start));  
 51         END;  
 52  IF @end = 0 --no end delimiter to last string  
 53             BREAK; --no more  
 54         SELECT @token = SUBSTRING(@Json, @Start + 1, @end - 1);  
 55         SELECT @token = REPLACE(@token, substitutions.FromString, substitutions.ToString)  
 56           FROM (   SELECT '\"' AS FromString,  
 57                           '"' AS ToString  
 58                    UNION ALL  
 59                    SELECT '\\',  
 60                           '\'  
 61                    UNION ALL  
 62                    SELECT '\/',  
 63                           '/'  
 64                    UNION ALL  
 65                    SELECT '\b',  
 66                           CHAR(08)  
 67                    UNION ALL  
 68                    SELECT '\f',  
 69                           CHAR(12)  
 70                    UNION ALL  
 71                    SELECT '\n',  
 72                           CHAR(10)  
 73                    UNION ALL  
 74                    SELECT '\r',  
 75                           CHAR(13)  
 76                    UNION ALL  
 77                    SELECT '\t',  
 78                           CHAR(09)  
 79                    UNION ALL  
 80                    SELECT '゛',  
 81                           CHAR(09)) substitutions;  
 82         SELECT @result = 0,  
 83                @Escape = 1;  
 84         WHILE @Escape > 0  
 85         BEGIN  
 86             SELECT @index = 0,  
 87                    @Escape = PATINDEX('%\x[0-9a-f][0-9a-f][0-9a-f][0-9a-f]%', @token);  
 88             IF @Escape > 0 --if there is one  
 89             BEGIN  
 90                 WHILE @index < 4 --there are always four digits to a \x sequence  
 91                 BEGIN  
 92                     SELECT --determine its value  
 93                         @result  
 94                         = @result + POWER(16, @index)  
 95                           * (CHARINDEX(SUBSTRING(@token, @Escape + 2 + 3 - @index, 1), @characters) - 1),  
 96                         @index = @index + 1;  
 97                 END;  
 98                 SELECT @token = STUFF(@token, @Escape, 6, NCHAR(@result));  
 99             END;  
100         END;  
101         INSERT INTO @Strings (StringValue)  
102         SELECT @token;  
103         SELECT @Json = STUFF(@Json, @Start, @end + 1, '@string' + CONVERT(NVARCHAR(5), @@identity));  
104     END;  
105     WHILE 1 = 1 --forever until there is nothing more to do  
106     BEGIN  
107         SELECT @parent_ID = @parent_ID + 1;  
108         SELECT @FirstObject = PATINDEX('%[{[[]%', @Json COLLATE SQL_Latin1_General_CP850_BIN); --object or array  
109         IF @FirstObject = 0  
110             BREAK;  
111         IF (SUBSTRING(@Json, @FirstObject, 1) = '{')  
112             SELECT @NextCloseDelimiterChar = '}',  
113                    @Type = 'object';  
114         ELSE  
115             SELECT @NextCloseDelimiterChar = ']',  
116                    @Type = 'array';  
117         SELECT @OpenDelimiter = @FirstObject;  
118         WHILE 1 = 1 --find the innermost object or list...  
119         BEGIN  
120             SELECT @lenJSON = LEN(@Json + '|') - 1;  
121             SELECT @NextCloseDelimiter = CHARINDEX(@NextCloseDelimiterChar, @Json, @OpenDelimiter + 1);  
122             SELECT @NextOpenDelimiter  
123                 = PATINDEX('%[{[[]%', RIGHT(@Json, @lenJSON - @OpenDelimiter)COLLATE SQL_Latin1_General_CP850_BIN); --object  
124             IF @NextOpenDelimiter = 0  
125                 BREAK;  
126             SELECT @NextOpenDelimiter = @NextOpenDelimiter + @OpenDelimiter;  
127             IF @NextCloseDelimiter < @NextOpenDelimiter  
128                 BREAK;  
129             IF SUBSTRING(@Json, @NextOpenDelimiter, 1) = '{'  
130                 SELECT @NextCloseDelimiterChar = '}',  
131                        @Type = 'object';  
132             ELSE  
133                 SELECT @NextCloseDelimiterChar = ']',  
134                        @Type = 'array';  
135             SELECT @OpenDelimiter = @NextOpenDelimiter;  
136         END;  
137         SELECT @Contents = SUBSTRING(@Json, @OpenDelimiter + 1, @NextCloseDelimiter - @OpenDelimiter - 1);  
138         SELECT @Json  
139             = STUFF(  
140                   @Json,  
141                   @OpenDelimiter,  
142                   @NextCloseDelimiter - @OpenDelimiter + 1,  
143                   '@' + @Type + CONVERT(NVARCHAR(5), @parent_ID));  
144         WHILE (PATINDEX('%[A-Za-z0-9@+.e]%', @Contents COLLATE SQL_Latin1_General_CP850_BIN)) <> 0  
145         BEGIN  
146             IF @Type = 'Object' --it will be a 0-n list containing a string followed by a string, number,boolean, or null  
147             BEGIN  
148                 SELECT @SequenceNo = 0,  
149                        @end = CHARINDEX(':', ' ' + @Contents); --if there is anything, it will be a string-based name.  
150                 SELECT @Start = PATINDEX('%[^A-Za-z@][@]%', ' ' + @Contents); --AAAAAAAA  
151                 SELECT @token = SUBSTRING(' ' + @Contents, @Start + 1, @end - @Start - 1),  
152                        @EndOfName = PATINDEX('%[0-9]%', @token COLLATE SQL_Latin1_General_CP850_BIN),  
153                        @param = RIGHT(@token, LEN(@token) - @EndOfName + 1);  
154                 SELECT @token = LEFT(@token, @EndOfName - 1),  
155                        @Contents = RIGHT(' ' + @Contents, LEN(' ' + @Contents + '|') - @end - 1);  
156                 SELECT @name = StringValue  
157                   FROM @Strings  
158                  WHERE String_ID = @param; --fetch the name  
159             END;  
160             ELSE  
161                 SELECT @name = NULL,  
162                        @SequenceNo = @SequenceNo + 1;  
163             SELECT @end = CHARINDEX(',', @Contents); -- a string-token, object-token, list-token, number,boolean, or null  
164             IF @end = 0  
165                 SELECT @end = PATINDEX('%[A-Za-z0-9@+.e][^A-Za-z0-9@+.e]%', @Contents + ' ') + 1;  
166             SELECT @Start = PATINDEX('%[^A-Za-z0-9@+.e][A-Za-z0-9@+.e]%', ' ' + @Contents);  
167             --select @start,@end, LEN(@contents+'|'), @contents  
168             SELECT @value = RTRIM(SUBSTRING(@Contents, @Start, @end - @Start)),  
169                    @Contents = RIGHT(@Contents + ' ', LEN(@Contents + '|') - @end);  
170             IF SUBSTRING(@value, 1, 7) = '@object'  
171                 INSERT INTO @hierarchy (NAME,  
172                                         sequenceNo,  
173                                         parent_ID,  
174                                         StringValue,  
175                                         Object_ID,  
176                                         ValueType)  
177                 SELECT @name,  
178                        @SequenceNo,  
179                        @parent_ID,  
180                        SUBSTRING(@value, 8, 5),  
181                        SUBSTRING(@value, 8, 5),  
182                        'object';  
183             ELSE IF SUBSTRING(@value, 1, 6) = '@array'  
184                 INSERT INTO @hierarchy (NAME,  
185                                         sequenceNo,  
186                                         parent_ID,  
187                                         StringValue,  
188                                         Object_ID,  
189                                         ValueType)  
190                 SELECT @name,  
191                        @SequenceNo,  
192                        @parent_ID,  
193                        SUBSTRING(@value, 7, 5),  
194                        SUBSTRING(@value, 7, 5),  
195                        'array';  
196             ELSE IF SUBSTRING(@value, 1, 7) = '@string'  
197                 INSERT INTO @hierarchy (NAME,  
198                                         sequenceNo,  
199                                         parent_ID,  
200                                         StringValue,  
201                                         ValueType)  
202                 SELECT @name,  
203                        @SequenceNo,  
204                        @parent_ID,  
205                        StringValue,  
206                        'string'  
207                   FROM @Strings  
208                  WHERE String_ID = SUBSTRING(@value, 8, 5);  
209             ELSE IF @value IN ( 'true', 'false' )  
210                 INSERT INTO @hierarchy (NAME,  
211                                         sequenceNo,  
212                                         parent_ID,  
213                                         StringValue,  
214                                         ValueType)  
215                 SELECT @name,  
216                        @SequenceNo,  
217                        @parent_ID,  
218                        @value,  
219                      'boolean';  
220             ELSE IF @value = 'null'  
221                 INSERT INTO @hierarchy (NAME,  
222                                         sequenceNo,  
223                                         parent_ID,  
224                                         StringValue,  
225                                         ValueType)  
226                 SELECT @name,  
227                        @SequenceNo,  
228                        @parent_ID,  
229                        @value,  
230                        'null';  
231             ELSE IF PATINDEX('%[^0-9]%', @value COLLATE SQL_Latin1_General_CP850_BIN) > 0  
232                 INSERT INTO @hierarchy (NAME,  
233                                         sequenceNo,  
234                                         parent_ID,  
235                                         StringValue,  
236                                         ValueType)  
237                 SELECT @name,  
238                        @SequenceNo,  
239                        @parent_ID,  
240                        @value,  
241                        'real';  
242             ELSE  
243                 INSERT INTO @hierarchy (NAME,  
244                                         sequenceNo,  
245                                         parent_ID,  
246                                         StringValue,  
247                                         ValueType)  
248                 SELECT @name,  
249                        @SequenceNo,  
250                        @parent_ID,  
251                        @value,  
252                        'int';  
253   
254             IF @Contents = ' '  
255                 SELECT @SequenceNo = 0;  
256         END;  
257     END;  
258     RETURN;  
259 END;

 



这篇关于SQL解析Json的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程