Json handling reference

Hi,

What is the best reference for json handling with TMS webcore. I'd also would like to produce efficient code. 
I'm little bit confused with TJsonObject, TJsObject etc.
Especially this is hard because my code completion isn't working. 



Mika:

My book has a couple of examples and also sheds light on how to consume JSON from other web services. I got some feedback from readers about that part and they all were pretty happy that they are now able to use JSON without issues.

We added the unit WEBLib.JSON that has a set of objects with interfaces similar to what the Delphi RTL offers, so you should be able to use a similar approach as you would use from a class Delphi VCL application.
With respect to code-completion, please verify your library path and make sure your library path DOES NOT contain paths to units of TMS WEB Core run-time. If you have only TMS WEB Core design-time units in your library path, code completion should work (Component Library Source folder)

Alternatively you can also use FNC, which has a set of JSON functions that can be used to access data. The functions are included in the WEBLib.TMSFNCUtils unit. Please note that this is for access only, not for building up JSON.

class function GetJSONProp(AJSONValue: TJSONValue; APropertyName: string): string;
class function GetJSONValueAsString(AJSONValue: TJSONValue): string;
class function GetJSONValue(AJSONValue: TJSONValue; APropertyName: string): TJSONValue;
class function GetJSONDoubleValue(AJSONValue: TJSONValue; APropertyName: string): Double;
class function GetJSONValueAsDouble(AJSONValue: TJSONValue): Double;
class function GetJSONIntegerValue(AJSONValue: TJSONValue; APropertyName: string): Integer;
class function GetJSONValueAsInteger(AJSONValue: TJSONValue): Integer;
class function IsJSONTrue(AJSONValue: TJSONValue): Boolean;
class function IsJSONFalse(AJSONValue: TJSONValue): Boolean;
class function GetJSONArraySize(AJSONArray: TJSONArray): Integer;
class function GetJSONArrayItem(AJSONArray: TJSONArray; AIndex: Integer): TJSONValue;
class function GetJSONObjectSize(AJSONObject: TJSONObject): Integer;
class function GetJSONObjectItem(AJSONObject: TJSONObject; AIndex: Integer): TJSONValue;
class function GetJSONObjectName(AJSONObject: TJSONObject; AIndex: Integer): string;
class function ParseJSON(AJSON: string): TJSONValue;

I found a lot of clues in delphi stackoverflow. The Flick book can get you started but its not quite enough. I had to do a lot of experimenting and reading the TMS Web source code to get something working. How complex is your data structure, is it nested?

Sauro: Noting very complex. I was just confused of TJs* and tJson*. Also as I mentioned My code completition isn't working, which makes it hard to guess.

Mr. Fierens:
I removed all other Webcore paths from library except component Library source folder Here is what i have now. Probably should move to 10.4 for these projects. :)

Holger: I have your book and I like it. But one just can't press Ctrl-F on book :) Actually the Json part there is most used.

Your library path looks good. Not sure why code completion isn't working. Is it already not working when you create a new TMS WEB Core project?

It works well , but after adding at least one of the following to uses clause: xdata.web.dataset, xdata.web.connection it stops working.
accoring to my tests following units don't break code completion
js,
weblib.json,
XData.Web.JsonDataset,
weblib.DB,
weblib.DBCtrls,
weblib.Buttons,
weblib.Graphics,
weblib.Controls,
weblib.Forms,
weblib.Dialogs,
weblib.StdCtrls,
weblib.ExtCtrls,
XData.Web.Request;

Actually I now have one dummy unit where I study these json class members with completion.

@wlandgraf

Nested data structures require loops or recursion which is not part of a framework but of programming techniques. All the classes available are covered and JSON simply does not offer more than arrays, objects, and primitive types.

This is great feedback. I also got the impression and provided more JSON examples in Hands On 1.

"Nohting very complex. I was just confused of TJs* and tJson*" I agree was also confused with the various classes and how to use them especially casting to get the particular value types.

I would definitely recommend providing more examples in your book (I also have a copy and it was a welcome addition) on how to read and write json in more complex situations, eg how to deal with nesting, arrays, how to use the pair functions and how to extract values.

Sauro:

All the examples you quote are provided. Using multiple loops inside of each other is programming language-specific and should not be the topic of a book for web programming in my opinion.

Your book, your content. I won't argue with that.

Sauro:

It was not meant to be harsh, but the problem is that you have to find some ‘level’ where you stop explaining things. I remember that I have an example in either Hands-on 1 or 2 (not released yet) uses a multi-level JSON with two arrays.

If you have issues, I will look if it is in I and point you to it.

Thanks for supporting my books with your purchase.

No problem, I understand you can't put everything in, you cover a lot anyway. I might write up some notes myself and distribute them. Out of curosity, one question I do have which I've not been able to answer is, given a JSON script such as:

{
"name": "John Smith",
"address": "Main Street",
"city": "New York"
}

Is there a way to find out how many fields there and whether it is possible to iterate through them? I noticed in other framworks there are programmatic techniques but I didn't see anything in TMS Web Core.

Well... i have been wondering also the same and also how to check if key exists.
I just now realized that TJsObject is actually pure javascript object (I read this couple of days ago from some post here - a long way from eyes to brain)

var
  a: TJSON;
  j: TJSObject;
  js: TJSONObject;
begin
  a := TJSON.Create;
  try
    js := a.Parse('{"a":1, "b":"test", "c":false,"d":{"d1":"aa","d2":"dddd"}}');
    j := js.JSObject;
    showmessage(inttostr(length(TJsObject.keys(j))));
    if j.hasOwnProperty('d') then
      showmessage('has d');
  finally
    a.Free; // is this necessary 
  end;
end;

and it produces quite nice code.
But since in this case we assign pure constant to JsObject this can be written

var
  j: TJSObject;
begin
    asm j = {"a":1, "b":"test", "c":false,"d":{"d1":"aa","d2":"dddd"}} end;
    showmessage(inttostr(length(TJsObject.keys(j))));
    if j.hasOwnProperty('d') then
      showmessage('has d');
end;

Pieter posted the functions from TMSFNCUtils. The first one yields the number of properties and you can iterate them getting the its name and value using the two others: