delphi Json操作
Creating a Simple JSON Object
The following code segment demonstrates the creation of a simple JSON object containing one JSON pair. Once this object is created, its ToString method is invoked, assigning the returned string representation of the JSON object to the top memo field that appears on the main form.
Because you can pass a JSON pair to the constructor of a TJSONObject, the first two lines of the try clause could have been replaced with a single line. Furthermore, since we passed a literal string to the TJSONString constructor, we could just as easily have passed the literal in place of the call to TJSONString.Create. The first two lines of the try clause could have been written like the following:
Regardless of which technique you use, the result will look like the following:
Creating JSON Numbers
You create JSON numbers using the TJSONNumber class. You can pass either a numeric literal or a string to the constructor of the TJSONNumber class. If you pass a string, you should ensure that it can be converted to a valid number. If the string value is not a number, you will end up with an invalid JSON value in your JSON object.
The following code, associated with the button labeled Create JSON Numbers, demonstrates how to create several different numbers. Notice that the argument to the TJSONNumber constructor in the second JSON pair is a string.
Creating Booleans and Nulls
You create Boolean values using the TJSONTrue and TJSONFalse classes. Likewise, you create null values in your JSON object using TJSONNull. This is demonstrated in the following code example, which is associated with the button labled Creating JSON true, false, and null.
This code produces the following result:
Creating JSON Arrays
JSON arrays are a bit more involved that the other simple classes. When calling the constructor of a TJSONArray you can pass no parameters, a single TJSONValue, two TJSONValues, or two strings. If you pass one or more arguments, those passed objects will appear as the first objects in the array. If you pass no arguments, or need to add additional elements to the array, you can subsequently call the Add or AddElement methods of the TJSONArray class.
Use the Add method to add a TJSONObject or TJSONArray to the array, or to add a literal string, number, Boolean, or null. AddElement permits you to add any TJSONValue, and you must use AddElement if you want to add a value returned by the TJSONString, TJSONNumber, TJSONTrue, TJSONFalse, or TJSONNull constructors.
The use of Add and AddElement are shown in the following code, which is associated with the button labeled Create JSON Arrays.
This code produces the following result:
Reading JSON Objects
JSON objects are text-based descriptions of data. This text is often transferred from an end point where the JSON object is created, to an end point where the data is consumed. Converting a JSON object to text is a simple matter of calling the ToString method of the top-level JSON object.
Converting a string that represents a JSON object into a JSON object is also straightforward. You do this by calling the ParseJSONValue class method of the TJSONObject class. This is shown in the following pseudo code:
As this code sample implies, the JSON object needs to be freed once you are done using it. Failure to do so will result in a memory leak by the top-level JSON object, as well as all of the JSON values that it contains.
Reading JSON Pairs
Every top-level JSON Object contains at least one JSON pair, and you must call the Get method of the TJSONObject class to retrieve a reference to this object.
There is a second method that returns a JSON pair from a JSON object, and that method is RemovePair. Note, however, that RemovePair both returns the JSON pair and removes it from the JSON object. Once removed, you become responsible for managing the life cycle of the removed pair, as well as all of the JSON values contained in that pair, if present. As a result, it is rare to use RemovePair when reading JSON values, unless your purpose is to change the JSON object.
When you call Get, you pass the zero-based ordinal position of the TJSONPair that you want to reference. Since all meaningful TJSONObjects have at least one TJSONPair, Get(0) should always return a TJSONPair. You can determine how many JSON pairs the top-level TJSONObject contains using the Size method.
Once you have a reference to a JSON pair, you can read the name part using the Value property of the JsonString property of the TJSONPair. The value part of the JSON pair is read using the Value property of the JsonValue property of the TJSONPair.
The use of ParseJSONValue and Get are demonstrated in the following code, which is associated with the button labeled Read JSON Object:
This code produced the following output:
The Get method is overloaded, permitting you to reference a JSON pair by name. For example, imagine that you want to refer to the JSON pair created by the WriteJSONObjectsClick event handler, with a name of Delphi and a value of Supports JSON. You can use code similar to the following:
Again, it is important to note that JavaScript is case sensitive. As a result, the string that you pass to the Get method is case sensitive as well. In the preceding code, if you had used 'delphi' as the parameter to the Get call, Get would have returned nil.
Reading String, Number, True, False and Null JSON Values
All TJSONValue instances have a Value property that returns a String representation of the value. For TJSONNumber, you will also find AsInt and AsDouble properties, which return the numeric value of the JSON number.
Using both the Value and AsDouble properties of a TJSONNumber is shown in the following code, which is associated with the button labeled Read JSON Numbers.
The preceding code produces the following output.
Reading TJSONTrue, TJSONFalse, and TJSONNull values are demonstrated in this event handler, which is associated with the button labeled Read JSON true, false, and null.
This code produces this output:
Reading JSON Arrays
A JSON array contains one or more JSON values. You access the values of an array by position, calling Get and passing the zero-based ordinal position of the array element you want to access. Use the TJSONArray Size property to determine how many elements the array contains.
The following code demonstrates how to read the elements of a JSON array:
The preceding code produces the following output:
A Generic Example
Using the techniques presented in this article you can parse any TJSONObject instance into its individual components. This is demonstrates in the following event handler, which uses recursion to walk a TJSONObject and output its values to the Memo shown in Figure 3.
procedure ParseJSONPairs(jo: TJSONObject); forward;
procedure Indentation(Increase: Boolean); begin if Increase then Indent := Indent + ' ' else Indent := copy(Indent, 1, Length(Indent) - IndentSize); end;
procedure WriteJSONValue(ancestor: TJSONAncestor); var jp: TJSONPair; jv: TJSONValue; begin Memo2.Lines.Add(Indent + ancestor.ClassName); if ancestor is TJSONPair then begin jp := TJSONPair(ancestor); Memo2.Lines.Add(Indent + 'ToString: ' + jp.ToString); Memo2.Lines.Add(Indent + 'JsonString: ' + jp.JsonString.Value); if (jp.JSONValue is TJSONTrue) or (jp.JSONValue is TJSONFalse) or (jp.JSONValue is TJSONNull) then Memo2.Lines.Add(Indent + 'JsonValue: ' + jp.JsonValue.ToString) else Memo2.Lines.Add(Indent + 'JsonValue: ' + jp.JsonValue.Value) end else begin jv := TJSONValue(ancestor); Memo2.Lines.Add(Indent + 'ToStrint: ' + jv.ToString); Memo2.Lines.Add(Indent + 'Value: ' + jv.Value); end; end;
procedure ParseJSONArray(ja: TJSONArray); var i: Integer; begin for i := 0 to ja.Size -1 do begin if ja.Get(i) is TJSONArray then begin Memo2.Lines.Add(Indent + 'JSONArray'); Indentation(True); ParseJSONArray(ja.Get(i) as TJSONArray); Indentation(False); end else if ja.Get(i) is TJSONObject then begin Memo2.Lines.Add(Indent + 'JSONObject'); Indentation(True); ParseJSONPairs(ja.Get(i) as TJSONObject); Indentation(False); end else WriteJSONValue(ja.Get(i)); end; end;
procedure ParseJSONPairs(jo: TJSONObject); var i: Integer; jv: TJSONValue; begin for i := 0 to jo.Size - 1 do begin jv := jo.Get(i).JsonValue; if jv is TJSONOBject then begin Memo2.Lines.Add(Indent + 'TJSONObject'); Indentation(True); ParseJSONPairs(jv as TJSONObject); Indentation(False); end else if jv is TJSONArray then begin Memo2.Lines.Add(Indent + 'TJSONArray'); Indentation(True); ParseJSONArray(jv as TJSONArray); Indentation(False); end else WriteJSONValue(jo.Get(i)); end; end;
begin if Memo1.Lines.Text = '' then begin ShowMessage('Display a JSON object in memo and try again'); exit; end; Indent := ''; Memo2.Clear; jo := TJSONObject.ParseJSONValue(Memo1.Lines.Text) as TJSONObject; try ParseJSONPairs(jo); finally jo.Free; end; end;
Figure 3. The JSONDemo project. The JSON that appears in the top memo field is parsed by the event handler attached to the button labeled Read Generic JSON.
Summary
JSON is a hierarchical, text-based mechanism for describing data. Similar to XML, though generally much shorter in length, JSON has quickly become a popular format for communicating data between processes.
In the next issue, I will demonstrate a number of advanced JSON techniques, along with a convenient tool for viewing JSON within Delphi's debugger.