Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Avoid sorted properties by using AMEMBERS()

Status
Not open for further replies.

Irwin1985

Programmer
Feb 2, 2017
44
ES
Hi everyone,

if you try this example:

Code:
CLEAR
obj = CREATEOBJECT("Empty")
ADDPROPERTY(obj, "c", "c content")
ADDPROPERTY(obj, "b", "b content")
ADDPROPERTY(obj, "a", "a content")
AMEMBERS(aProp, obj)
DISPLAY MEMORY LIKE aProp

you'll notice that AMEMBERS() function retrieves an ordered array but do you know any trick to avoid this?, I want my object's properties as it is.

thanks!

A team is only pieces that you exchange until you finish the work, it is efficient, it works.
 
You'll read the list more often than you write to it, ie you more often add commas than you remove them, if you don't simply have them by standard within the property.

And even writing to it is simply adding name+','.
Processing the list also is easy if you let ALINEs remove empty elements, it's an option in the flags.

Chriss
 
Code:
cMemberlist         = ","
cMemberlistNoCommas = SPACE(0)

This.cMemberlist         = This.cMemberlist         + tcProperty + ","
This.cMemberlistNoCommas = This.cMemberlistNoCommas + IIF(NOT EMPTY(this.cMemberlistNoCommas), ",", SPACE(0)) + tcProperty

This.cMemberlist         =         STRTRAN(      This.cMemberlist,               ","+tcProperty+",",",",1,1,2)
This.cMemberlistNoCommas = ALLTRIM(STRTRAN("," + This.cMemberlistNoCommas + ",", ","+tcProperty+",",",",1,1,1), 1, ",")

You could do both.

--
Rick C. Hodgin
 
Yes, and options 1 are shorter, aren'T they? For sake of normal operations on comma delimited lists, chosse optioon 2, if you like.

I think it's still not fully compatible to using empty objects with ADDPROPERTY, so you have to rewirite how the JSON parser adds properties. If you do it by ADDPROPERTY(oJSON,cproperty,vValue) you circumvent the This_Access method and just add the property without adding to the cMemberlist. That's the greater weakness of this. I first thought Thi_Access would also be called if you access just This, not a member of This, but that's not the case.

Or, to let the code speak for itself:
Code:
goApp = CREATEOBJECT("myappclass")

oJson = CREATEOBJECT("JSON")
&& adding property by assignment
oJSon.foo = "bar"
oJson.easy = .t.
oJson.abc = 123

CREATE CURSOR Properties (z int, x int, y int, a int, b int)
APPEND BLANK

&& adds properties to oJson, without going through This.Access
SCATTER NAME oJson Additive

suspend && look foryourself in the Locals window of the debugger, for example
goApp.lJSONRedirect = .f.
&& adds properties to object, where they belong:
SCATTER NAME oJson.object Additive && but not to the memberlist

In the last case the only call to This_access is about tcMember = 'object', of course. But you don't know what's done with the object, what properties are added. or removed or what else might be done to it.

So to point out the essence: Even with this_access not every access is under your control.

You could still use it when you act with the necessary discipline, so make it internal knowledge and usage to add properties by just setting them and not by scattering them, a parser will parse properties one by one anyway.

Or you change the whole idea to keep member lists in meta data and then only have to worry about that in the actual JSON library, not in the single Json objects. Each object instance could have an id given by the index in a collection, for example, and then you can store anything in tables you want to store about the objects. You have to keep track about valid object references in the collection, but I think it's manageable. That poses another soft rule to only let the json library act on json objects, any other code can just work with the objects themselves, after they got their properties and values populated and shouldn't interfere with the object structure anymore.

Anyway you turn it, it goes into the territory of working, if you don't misuse it. Well, it sounds worse than it is, becasue thet's a very general truth about any code and doesn't stop anyone from programming.

Chriss
 
I look at the simplicity of this approach and find it appealing. It lets you keep the native order and it filters out default members. And if you need to have names that might be used in the class, then prefix everything added with an underscore and the whole thing becomes academic.

Code:
lo = CREATEOBJECT("label")
lo.AddProperty("lValue", .t.)
lo.AddProperty("cValue", "test")
lo.SaveAsClass("c:\temp\test.vcx", "test_class")

USE c:\temp\test.vcx
LOCATE FOR NOT EMPTY(Timestamp)  && Could also use GOTO 2
ALINES(laLines, Properties)

loRef = CREATEOBJECT("label")
AMEMBERS(laMembers, loRef)

FOR lnI = 1 TO ALEN(LaLines, 1)
    IF ASCAN(laMembers, UPPER(GETWORDNUM(laLines[lnI], 1))) = 0
        ? laLines[lnI]
    ENDIF
NEXT

You can pass around the object as needed, and then a few functions crafted around this approach would yield everything you need for serialization and also deserialization (if you needed those things).

The whole key is the natural order. If you don't need natural order then it doesn't matter how you approach it.

--
Rick C. Hodgin
 
I'm going to stop posting here at Tek-Tips because every time I do I get these hate vibes.

They're not appreciated.

--
Rick C. Hodgin
 
I'm going to stop posting here at Tek-Tips because every time I do I get these hate vibes.

Rick, please PLEASE think again.

If anyone is posting "hate vibes" or any other sort of objectionable or offensive messages, it would be much better to report them, via the "red flag" icon. Doing so not only discourages those particular posts, but is of benefit to the community as a whole.

If you simply walk away from the forum, well, that's your choice. But we would all miss the benefit of the good advice and experience that you share. And to say that your advice is not appreciated is absolutely untrue - witness the fact that you have become listed as one of the top four "MVPs" in the short time since you joined.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I'm sorry if you interpret the discussion as hate vibe. I'm talking through pros and cons and in my latest posts actually show some deficits about the solution using This_Access.
I reject your alternatives, that's true, but that differs from hate. Of course you can do both. You might find it unelegant to start a list with a comma (and also end it that way) permanently instead of only for the use case of exact search of a property name. To me that's private or hidden and only for internal use, so it's just the concern of the Json implementation, the usage of the objects that result from parsing is still 1:1 and the serialization can turn off the redirection and get at the member list.

You're right that this all is quite academic, but then the major concern of Irwin was trading this little advantage of property order for the speed of the lightweight empty class in comparison to any other base class. Mike mentioned it would be a nice intellectual challenge. That's the only reason I started experimenting with the idea.

I also already warned the order of properties does not prevent that creating the JSON string 1:1 as the original if no value changed will also depend on indentation, tabs, spaces, where you set brackets, etc. So it's not done with that anyway.

I think there would even be a much simpler solution to get back to the original JSON: Just turn it into a template for textmerge by replacing the property values in it to the object members and then it won't matter what amember sorts or not, you'd just textmerge the current object values into the template and you're done. The order and positioning and tabs etc. is preserved.

To make this more concrete, when the JSON parser determines the properties and their values, it can replace those JSON string parts with textmerge placeholders. Well, actually just the values, like this:

Code:
{
  "c": "c value" 
  "a": "a value"
  "b": "b value"
}

This could be parsed into an object with a,b,c properties and their values, no matter in which order they are organized, but you siply also store the JSON as template:
Code:
{
  "c": "<<object.c>>" 
  "a": "<<object.a>>"
  "b": "<<object.b>>"
}

This should be easy to do while parsing, as you know the property names and values and their positions while parsing and so can use Stuff() to turn the parse JSON into such a textmerge template.

There are pros and cons with that too. If you only ever want to output the same structure it's fine, if you would like to add properties and output them, too, when you serialize, that'll not help. You could even make the object name a variable in this, as textmerge supports recursive processing, ie placeholders within placeholders.

To get to the point, this way you also simply have the JSON as it originally was formatted.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top