dcsimg
Results 1 to 13 of 13

Thread: JSON with values array and cCollection

  1. #1

    Thread Starter
    Junior Member oldVBDev's Avatar
    Join Date
    Aug 2018
    Posts
    18

    JSON with values array and cCollection

    Hi for all.
    I have this class:
    Code:
    Option Explicit
    Public Properties As vbRichClient5.cCollection
    
    Public Property Get FirstProp() As String
        FirstProp = Properties("FirstProp")
    End Property
    
    Public Property Let FirstProp(ByVal strValue As String)
        Properties.Prop("FirstProp") = strValue
    End Property
    
    Public Property Get SecondProp() As String
        SecondProp = Properties("SecondProp")
    End Property
    
    Public Property Let SecondProp(ByVal strValue As String)
        Properties.Prop("SecondProp") = strValue
    End Property
    
    Private Sub Class_Initialize()
        Set Properties = New_c.JSONObject
    End Sub
    With it I must generate a JSON.
    Can I to have how property with a list of value?
    And if I use the method cCoo.Properties.SerializeToJSONString , I will have an array in the JSON?

    Thanks

  2. #2

    Thread Starter
    Junior Member oldVBDev's Avatar
    Join Date
    Aug 2018
    Posts
    18

    Re: JSON with values array and cCollection

    Hi for all.
    I have solved this way:
    Code:
    Option Explicit
    Public Properties As vbRichClient5.cCollection
    
    Public Property Get FirstProp() As String
        FirstProp = Properties("FirstProp")
    End Property
    
    Public Property Let FirstProp(ByVal strValue As String)
        Properties.Prop("FirstProp") = strValue
    End Property
    
    Public Property Get SecondProp() As String
        SecondProp = Properties("SecondProp")
    End Property
    
    Public Property Let SecondProp(ByVal strValue As String)
        Properties.Prop("SecondProp") = strValue
    End Property
    
    Public Property Get ArrayValue() As String
        SecondProp = Properties("ArrayValue")
    End Property
    
    Public Property Set ArrayValue(objValue As cCollection)
        Set Properties.Prop("ArrayValue") = objValue
    End Property
    
    Private Sub Class_Initialize()
        Set Properties = New_c.JSONObject
    End Sub
    
    Private Sub Form_Load()
        Dim lc_Class  As New cClass
        Dim lc_Coll As New cCollection
        Dim str     As String
    
        With lc_Coll
            .Add "one"
            .Add "two"
        End With
    
        With lc_Class
            Set .ArrayValue = lc_Coll
            .FirstProp = "1"
            .SecondProp = "2"
            str = .Properties.SerializeToJSONString
        End With
    
        Debug.Print str
    End Sub
    and I get:
    {"ArrayValue":["one","two"],"FirstProp":"1","SecondProp":"2"}
    The result is right, but is the method correct?
    Schimdt, jbpro and the others what do they think?
    Thanks

  3. #3
    Frenzied Member
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    1,099

    Re: JSON with values array and cCollection

    Looks OK, but a couple of thoughts:

    • The Property Get ArrayValue should be returning a cCollection instead of a String and should not be setting "SecondProp"...so:


    Code:
    Public Property Get ArrayValue() As cCollection
        Set ArrayValue = Properties("ArrayValue")
    End Property
    • Maybe just my personal taste, but I don't like exposing the module level "Properties" collection publicly because misbehaving code can modify it directly as opposed to using the public properties. I'd rather have a separate GetJsonString or similarly named method like:


    Code:
    Private Properties As cCollection
    
    Public Function GetJsonString() As String
       GetJsonString = Properties.SerializeToJsonString
    End Function

  4. #4

    Thread Starter
    Junior Member oldVBDev's Avatar
    Join Date
    Aug 2018
    Posts
    18

    Re: JSON with values array and cCollection

    Quote Originally Posted by jpbro View Post
    Looks OK, but a couple of thoughts:

    • The Property Get ArrayValue should be returning a cCollection instead of a String and should not be setting "SecondProp"...so:


    Code:
    Public Property Get ArrayValue() As cCollection
        Set ArrayValue = Properties("ArrayValue")
    End Property
    • Maybe just my personal taste, but I don't like exposing the module level "Properties" collection publicly because misbehaving code can modify it directly as opposed to using the public properties. I'd rather have a separate GetJsonString or similarly named method like:


    Code:
    Private Properties As cCollection
    
    Public Function GetJsonString() As String
       GetJsonString = Properties.SerializeToJsonString
    End Function
    The first is a mistake of copying and pasting. Sorry!
    The second seems to me a good advice, but when you say "misbehaving code" do you mean a programming error?
    Thank.

  5. #5

    Thread Starter
    Junior Member oldVBDev's Avatar
    Join Date
    Aug 2018
    Posts
    18

    Re: JSON with values array and cCollection

    Hi for all.
    I changed the class like that:
    Code:
    Option Explicit
    Private Properties As vbRichClient5.cCollection
    Private myArray    As New cCollection
    
    Public Sub ArrayClear()
        myArray.RemoveAll
    End Sub
    
    Public Sub ArrayValueAdd(ByVal Item As Variant, Optional ByVal key As Variant)
        myArray.Add Item, key
        Set Properties.Prop("ArrayValue") = myArray
    End Sub
    
    Public Sub ArrayValueRemove(ByVal key As Variant)
        myArray.Remove key
        Set Properties.Prop("ArrayValue") = myArray
    End Sub
    
    Public Function GetJsonString() As String
        GetJsonString = Properties.SerializeToJSONString
    End Function
    
    Private Sub Class_Initialize()
        Set Properties = New_c.JSONObject
    End Sub
    
    Public Property Get FirstProp() As String
        FirstProp = Properties("FirstProp")
    End Property
    
    Public Property Let FirstProp(ByVal strValue As String)
        Properties.Prop("FirstProp") = strValue
    End Property
    
    Public Property Get SecondProp() As String
        SecondProp = Properties("SecondProp")
    End Property
    
    Public Property Let SecondProp(ByVal strValue As String)
        Properties.Prop("SecondProp") = strValue
    End Property
    and then
    Code:
    Private Sub Form_Load()
        Dim lc_Class As New cClass
        Dim str      As String
    
        With lc_Class
            .FirstProp = "1"
            .SecondProp = "2"
            .ArrayClear
            .ArrayValueAdd "one"
            .ArrayValueAdd "two"
            str = lc_Class.GetJsonString
        End With
    
        Debug.Print str
    End Sub
    I get the right output:
    Code:
    {"FirstProp":"1","SecondProp":"2","ArrayValue":["one","two"]}
    What do you think?

    Thanks

  6. #6
    PowerPoster
    Join Date
    Jun 2013
    Posts
    3,794

    Re: JSON with values array and cCollection

    Quote Originally Posted by oldVBDev View Post
    What do you think?
    I'd take care, that the New_c... constructor is used always (instead of VBs New Keyword),
    to make it easier with switching to regfree-mode (which would only require a drop-in *.bas module later)...

    Second thing is, although your code works (because the cCollection tolerates this) -
    it'd be better to use construct "JSON-flagged" cCollection-instances (New_c.JSONObject and New_c.JSONArray) -
    instead of a "plain cCollection-instance" (e.g. over New_c.Collection)...
    There is Properties in a cCollection, which will later identify such a "flagged instance"
    (.IsJSONArray ... or ... .IsJSONObject) which some "JSON-consuming Objects" might try
    to use, to easier identify "JSON-NodeTypes" - e.g. the cwTree-Widget does that, where you
    can "hang in" a (cCollection-based) JSON-Object, for visualizing in one line of code.

    You also might include some "basic-Properties" into such serializable Classes
    (like e.g. a Public JSON-Prop for reading of / initializing from JSON-String-content)

    Also, JSON-serializing is able to differentiate between these types (in VB, the appropriate Variant-Types are returned):
    - Boolean true/false (mapping to the VB6 vbBoolean-Variant-Type)
    - Numeric-Values (mapping to either Long/Currency/Decimal for Integers - or to a VB-Double for rational numbers)
    - String-Values (mapping to VBs String-Type)
    - null (mapping to the VB6-vbEmpty-VariantType)
    - Object - a Key/Value List (mapping to a cCollection, which has .IsJSONObject = True)
    - Array - a plain Value List without Keys (mapping to a cCollection, which has .IsJSONArray = True)

    So there's no need - to "turn everything into a JSON-String-Type" (Property-wrapping-wise - as shown in "SecondProp" below).

    Code:
    Option Explicit
    
    Private mProps As cCollection
     
    Private Sub Class_Initialize()
        Set mProps = New_c.JSONObject 'Inits of some important Props below
            mProps.Prop("FirstProp") = "Init-String"
            mProps.Prop("SecondProp") = 0
            mProps.Prop("MyArray") = New_c.JSONArray
    End Sub
    
    Public Property Get FirstProp() As String
        FirstProp = mProps("FirstProp")
    End Property
    Public Property Let FirstProp(ByVal strValue As String)
        mProps.Prop("FirstProp") = strValue
    End Property
    
    Public Property Get SecondProp() As Long
        SecondProp = mProps("SecondProp")
    End Property
    Public Property Let SecondProp(ByVal lngValue As Long)
        mProps.Prop("SecondProp") = lngValue
    End Property
    
    Public Property Get MyArray() As cCollection
        Set MyArray = mProps("MyArray")
    End Property
     
    Public Property Get JSON() As String
        JSON = mProps.SerializeToJSONString
    End Property
    Public Property Let JSON(ByVal strJSON As String)
        Set mProps = New_c.JSONDecodeToCollection(strJSON)
    End Property
    Form-TestCode...
    Code:
    Option Explicit
    
    Private Sub Form_Load()
        Dim oClass1 As New cClass
        Dim oClass2 As New cClass
        Dim strJSON As String
     
        oClass1.FirstProp = "String 1" 'assign a String-Value
        oClass1.SecondProp = 2         'assing a Long-Value
        oClass1.MyArray.RemoveAll
        oClass1.MyArray.Add "one"
        oClass1.MyArray.Add "two"
        strJSON = oClass1.JSON
     
        Debug.Print strJSON 'JSON-content of oClass1
        
        oClass2.JSON = strJSON 'now init the oClass2-instance from that content
        Debug.Print oClass2.JSON 'it should now (value-wise) be identical to the oClass1-instance
    End Sub
    HTH

    Olaf

  7. #7

    Thread Starter
    Junior Member oldVBDev's Avatar
    Join Date
    Aug 2018
    Posts
    18

    Re: JSON with values array and cCollection

    Hi Olaf. Hi for other.
    Sorry for delay.
    This way the code is consistent with the objects in your framework. Good.

    Another question. If I wanted to nest a JSon object is it possible?
    example:
    {"FirstProp":"String 1","SecondProp":2,"MyArray":["one","two"],{"subProp1":"11","SubProp2":"22"}}
    or
    {
    "accounting" : [
    { "firstName" : "John",
    "lastName" : "Doe",
    "age" : 23 },

    { "firstName" : "Mary",
    "lastName" : "Smith",
    "age" : 32 }
    ],
    "sales" : [
    { "firstName" : "Sally",
    "lastName" : "Green",
    "age" : 27 },

    { "firstName" : "Jim",
    "lastName" : "Galley",
    "age" : 41 }
    ]
    }
    I did some tests but I failed.

    Thanks.

  8. #8
    PowerPoster
    Join Date
    Jun 2013
    Posts
    3,794

    Re: JSON with values array and cCollection

    Quote Originally Posted by oldVBDev View Post
    If I wanted to nest a JSon object is it possible?
    Of course...
    You can nest both "node-types" (a JSON-Object, as well as a JSON-Array) -
    by simply assigning them as (Child)-JSON-Values, in the right way, according to what their JSON-Parent-Container demands...

    Assignments (or inserts) will happen against "JSON-Parent-Container-Slots" - and in case that Parent-Container is of type:
    - JSONObject - such a "Slot" is given by a Key (usually assigned via JSONParent.Prop("TheKey") = SomeValue_Including_JSONArraysOrObjects)
    - JSONArray - the Parent-Slot is addressed over an index - and assignment of new JSONValues usually happens via: JSONParent.Add SomeValue_Including_JSONArraysOrObjects

    For example (if we take the last Demo-Snippet from my post #6 as the Base),
    you already have a single "subnode-type" in there (under the Prop(Key), named "MyArray")

    If you want to include a SubNode of type JSONObject in addition, then you will have to enhance the Class_Initialize by:
    Code:
    Private Sub Class_Initialize()
        Set mProps = New_c.JSONObject 'Inits of some important Props below
            mProps.Prop("FirstProp") = "Init-String"
            mProps.Prop("SecondProp") = 0
            mProps.Prop("MyArray") = New_c.JSONArray
            mProps.Prop("MyObject") = New_c.JSONObject
    End Sub
    And the rest of the code about a Property, similar to the MyArray-Prop (which simply hands out the cCollection):
    Code:
    '...
    
    Public Property Get MyArray() As cCollection
       Set MyArray = mProps("MyArray")
    End Property
    
    Public Property Get MyObject() As cCollection
       Set MyObject = mProps("MyObject")
    End Property
    
    '...
    And that's it already, regarding "first-level-nesting of a JSON-Child-Object"...
    On the outside you could simply use it this way (to add new Members as Key-Value-Pairs):
    Code:
      With oClass1.MyObject
         .Prop("MyPropKey") = SomeJSONValueType
      End With
    HTH

    Olaf

  9. #9

    Thread Starter
    Junior Member oldVBDev's Avatar
    Join Date
    Aug 2018
    Posts
    18

    Re: JSON with values array and cCollection

    Hi Olaf. Hi for other.

    Of course ...
    I did not doubt that it was implemented!
    Another question:
    If I do not know in advance how many nodes I need, can they be allocated dynamically? From the example it does not seem.
    Thanks,
    oldVBDev

  10. #10
    PowerPoster
    Join Date
    Jun 2013
    Posts
    3,794

    Re: JSON with values array and cCollection

    Quote Originally Posted by oldVBDev View Post
    If I do not know in advance how many nodes I need, can they be allocated dynamically? From the example it does not seem.
    Thats because the example was based on a concrete (static) "Wrapper-Class"...
    If you want "the full dynamic behaviour" - then you should skip implementing JSON-stuff behind a (static) Wrapper-Class -
    and instead go with just "a generic cCollection as the Root-Object".

    E.g. if Root represents "a company", then you should write a Function to fill it "at Root-Level" -
    and additional Sub-Functions for *any* of those Values, which are either a JSONObject or a JSONArray...

    The following example demonstrates that ...
    (function which return a JSONObject have 'Obj' in their Name - those who return a JSONArray have 'Arr' in their name).

    Code:
    Option Explicit
    
    Private MemDB As cMemDB
    
    Private Sub Form_Load()
      Set MemDB = CreateDemoDB 'make some DemoDB, so that we can demonstrate JSON-generation from an Rs
     
      Dim Root As cCollection
      Set Root = PopulateCompanyObj()
      
      Debug.Print Replace(Root.SerializeToJSONString, "{", vbCrLf & "{")
    End Sub
    
    Function PopulateCompanyObj() As cCollection
      Set PopulateCompanyObj = New_c.JSONObject
      With PopulateCompanyObj
        .Prop("GenDate") = Now 'if you want, provide info when this Object was filled
        .Prop("CompanyName") = "The CompanyName" 'end-point-values are given directly
        .Prop("CustomersArr") = PopulateCustomersArr() 'node-values will always be set by a function
      End With
    End Function
     
    Function PopulateCustomersArr() As cCollection
      Set PopulateCustomersArr = New_c.JSONArray
      With PopulateCustomersArr
        Dim RsCustomers As cRecordset
        Set RsCustomers = MemDB.GetRs("Select * From Customers")
        Do Until RsCustomers.EOF
          .Add PopulateCustomerObjFromRsFields(RsCustomers.Fields)
          RsCustomers.MoveNext
        Loop
      End With
    End Function
    
    Function PopulateCustomerObjFromRsFields(Fields As cFields) As cCollection
      Set PopulateCustomerObjFromRsFields = New_c.JSONObject
      With PopulateCustomerObjFromRsFields
        Dim F As cField
        For Each F In Fields
          .Prop(F.Name) = F.Value
        Next
      End With
    End Function
          
    Function CreateDemoDB() As cMemDB
      Set CreateDemoDB = New_c.MemDB
          CreateDemoDB.Exec "Create Table Customers(ID Integer Primary Key, Name Text, ZipCode Text)"
      Dim i As Long
      For i = 1 To 10
        CreateDemoDB.ExecCmd "Insert Into Customers(Name, ZipCode) Values(?,?)", "Name " & i, 100 * i
      Next
    End Function
    the above prints out the following JSON:
    Code:
    {"GenDate":"2018-10-17 17:43:20","CompanyName":"The CompanyName","CustomersArr":[
    {"ID":1,"Name":"Name 1","ZipCode":"100"},
    {"ID":2,"Name":"Name 2","ZipCode":"200"},
    {"ID":3,"Name":"Name 3","ZipCode":"300"},
    {"ID":4,"Name":"Name 4","ZipCode":"400"},
    {"ID":5,"Name":"Name 5","ZipCode":"500"},
    {"ID":6,"Name":"Name 6","ZipCode":"600"},
    {"ID":7,"Name":"Name 7","ZipCode":"700"},
    {"ID":8,"Name":"Name 8","ZipCode":"800"},
    {"ID":9,"Name":"Name 9","ZipCode":"900"},
    {"ID":10,"Name":"Name 10","ZipCode":"1000"}]}
    HTH

    Olaf
    Last edited by Schmidt; Yesterday at 01:09 PM.

  11. #11

    Thread Starter
    Junior Member oldVBDev's Avatar
    Join Date
    Aug 2018
    Posts
    18

    Re: JSON with values array and cCollection

    Hi Olaf. Hi for other.
    Thank for your replay.
    Your code was a little complicated for me.
    I took some time to understand it. But I succeeded.
    I've brought your code back because maybe there's an "as ..." clause missing.
    I know it's not important.
    I inserted it. You say to me if it's true.
    Code:
    Function PopulateCustomerObjFromRsFields(Fields As cFields) as cCollection
      Set PopulateCustomerObjFromRsFields = New_c.JSONObject
      With PopulateCustomerObjFromRsFields
        Dim F As cField
        For Each F In Fields
          .Prop(F.Name) = F.Value
        Next
      End With
    End Function
    oldVBdev

  12. #12
    PowerPoster
    Join Date
    Jun 2013
    Posts
    3,794

    Re: JSON with values array and cCollection

    Quote Originally Posted by oldVBDev View Post
    Your code was a little complicated for me.
    I took some time to understand it. But I succeeded.
    Glad you took your time with it (it's not the norm in this forum).

    Quote Originally Posted by oldVBDev View Post
    I've brought your code back because maybe there's an "as ..." clause missing....
    Code:
    Function PopulateCustomerObjFromRsFields(Fields As cFields) as cCollection
    Good catch - thanks (added it into the example-code in my prior post now as well)...

    Olaf

  13. #13

    Thread Starter
    Junior Member oldVBDev's Avatar
    Join Date
    Aug 2018
    Posts
    18

    Re: JSON with values array and cCollection

    Thank for help Olaf.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width