Best practices for JSON handling? aka does golang have object.hasOwnProperty ?

435 views
Skip to first unread message

maxpow...@gmail.com

unread,
Jan 20, 2015, 10:03:08 PM1/20/15
to golan...@googlegroups.com
It's no secret I've been working with golang for a few weeks now to get a JSON based web API to backend a project.
My initial approach had me defining objects in golang that may go into or out of the DB and then using gorilla to handle serialization of posted data into & out of those objects and finally using a controller to handle persistence to a mongo store.

After a few weeks of this approach I've come to realize I have problem that I hadn't considered before and I'm not really sure how to address it correctly within Go.

Certain objects are strict models for instance a User comprises a username, password, creation time and a boolean that tells us whether or not this user is activated or not.
But then we get to something that's not so clear cut such as permissions.  My point might become more clear if I give you some background on the project.

I work with a healthcare network that is nationwide.  They have acquired several smaller organizations over time and the end result is a patchwork of various databases and systems in play, many of which duplicate functionality from eachother, but each has it's own "spin".

My task is to pilot a program to unify the information systems for the entire organization.  We are only speaking to documents, workflows and non-email based communications such as an in house chat client.
Of particular interest and concern is the documents area.  Because it's healthcare and most documents are either patient medical records or references to such we have to be very, very granular about who gets access to what documents and what privilege level they have within those documents.

For example, Becky in Nebraska works in compliance and should only have read level access to medical records.  Her job involves verifying that on the whole a Dr is not just ordering extra tests that are likely to be irrelevant.  Without going into how bad that may sound it is still a reality of the task at hand, that I make sure she only has access to documents created by Drs within the groups she is in charge of.

This produces a permissions object that is stored in the database under a collection called permissions looks like
permissions = {
  sources
:{
        midwestclinic
: [r],
        southvalleyregional
: [r],
        heartofmercy
: [r]
 
}
}



And this works out ok for Becky's case.  However if you consider a clinician, they need read access to every patient record for every patient under their care and read write access for every record created by themselves.
In fact the clinician ends up with a completely different model that looks more like.

permissions = {
     allowedtypes
:{
          medical
: {
               sources
:{
                    myself
: [*],
                    mylocation
:[r],
                    other
: [a] //(a is a flag meaning that we need to record the fact he accessed it, but otherwise it's open for reading)
               
}
         
}
}


Besides being significantly different in structure, the other problem we face is that in Becky's instance, the sources field describes distinct location labels which are stored within the document themselves.  Whereas in the case of the Dr, the sources field is a description of the relationship of the Dr to the document source.  Remapping them into a single object is probably not realistic. 

As you can see, these are completely different objects that in javascript could easily be filtered by an if(object.hasOwnProperty()) statement.

The permissions object can be multi-modal and we can't always be confident about the result of marshalling it into a predefined object.
My solution thus far has been to use the gorilla schema and a bunch of attempts to marshall into what I expect the most common permissions structures to look like.
This is producing a lot of boiler plate objects with very similar names who differ by very little, which is an anti-pattern telling me I'm doing it wrong.

It would be much better if we could just arbitrarily check for any field using the equivalent of javascript's, object.hasOwnProperty and then take action based on the presence or lack thereof of fields.

So far my reading on the subject hasn't lead me to an answer.
For the record I've read both http://blog.golang.org/json-and-go and http://golang.org/pkg/encoding/json/ and maybe I'm just not fully understanding them.
My lack of finding something suitable tells me I'm either missing something obvious, approaching the task completely wrong, or possibly both.

I'm open to ideas which is why I'm here asking for help and for bearing with me through this, thank you.

Tamás Gulácsi

unread,
Jan 21, 2015, 12:46:13 AM1/21/15
to golan...@googlegroups.com
What is this "allowedtypes"? Why doesn't Becky has one - why is the difference in the structure? Can't it be made similar?

maxpow...@gmail.com

unread,
Jan 21, 2015, 2:44:16 AM1/21/15
to golan...@googlegroups.com
Allowed types in this case references the types of documents the rule applies to since that is a base unit of account. 

I've simplified it to "medical", but in reality it's a huge list.  e.g. a medical assistant cannot have write permission on a prescription type, but may need to read it, however they may need to take patient vitals and thus would need write permission for a "patientvitals" document, both are subtypes of medicalrecord since they are information generated in response to a form and contain information regardng a patient. 

Beyond medicalrecord there are also completely different types that have nothing to do with patients.
A Dr may need read write on an interns employment records in order to do performance reviews and that is a whole other category of document called employmentrecords.  There's a dozen or so top level categories besides medical and employment, and each one maps to dozens (in one case hundreds) of subtypes and sub, sub,types. 

The model is kind of nuts and is one reason why a nosql store of some type seems to be the correct storage solution.  I am starting to think a graph database might alleviate some of the modelling overhead  

There isn't a way to really simplify this much more than it is.  What you see before you is the result of two different concepts of what permissions mean from 2 legacy systems being integrated into a singular system.
There are in fact dozens more of these because each acquired business unit had it's own way of attempting to comply with HIPAA and other regs.  In many cases there are things that are essentially the same, and duplicate one another.  Radiology at one hospital was/is handled by a RIS that has a completely different internal structure regarding who can do what, but in order to maintain continuity of care we have to import that whole set under a different heading that the regular radiology subcat of medicalrecords.
 
Now as the organization begins to coalesce over a single information system, we just need this to work :)

My philosophy in designing this has been driven by some concepts from golang, for example the concept of if it has an interface that meets the requirements for a type then it is an object of that type.
If a permission object contains an allowedtypes field then the permission record grants access only to those types.  If the allowed types field is missing then the permissions apply to all records.

Point blank, this job gets a whole lot easier if I can find the golang equivalent of "hasOwnProperty"

Egon

unread,
Jan 21, 2015, 3:11:05 AM1/21/15
to golan...@googlegroups.com, maxpow...@gmail.com

Although I wouldn't recommend doing it by that route, it's probably better to parse these types separately and then convert both into a single unified type. Duality of models can easily cause problems.

+ Egon

maxpow...@gmail.com

unread,
Jan 21, 2015, 3:35:03 AM1/21/15
to golan...@googlegroups.com, maxpow...@gmail.com
http://play.golang.org/p/z6V13J_qHI

Although I wouldn't recommend doing it by that route, it's probably better to parse these types separately and then convert both into a single unified type. Duality of models can easily cause problems.

+ Egon
 

As always Egon your code solution is beautiful and elegant and I actually really like that answer, since it precisely addresses the problem, but it's not going to scale with the problem space.
It increases in code complexity as I add the various cases and I think that complexity righfully belongs in the controller space, not the model space.

Looking at the code I do see a potential opportunity here though.
Is it possible to create a map containing strings for keys and interfaces for values?  Every value is going to be either
a string literal
an array of strings
another map of string/interfaces

Then just recursively drill through the object and return the value bound to a given label?  I realize this may be suboptimal, but the only other solution I see is to use Javascript directly somehow

I just need to know, given JSON object o does it have sub object n and does n contain field f,  and if so what is the value of o.n.f?  The trick is that n can be any depth.

Egon

unread,
Jan 21, 2015, 5:00:20 AM1/21/15
to golan...@googlegroups.com, maxpow...@gmail.com


On Wednesday, 21 January 2015 10:35:03 UTC+2, maxpow...@gmail.com wrote:
http://play.golang.org/p/z6V13J_qHI

Although I wouldn't recommend doing it by that route, it's probably better to parse these types separately and then convert both into a single unified type. Duality of models can easily cause problems.

+ Egon
 

As always Egon your code solution is beautiful and elegant and I actually really like that answer, since it precisely addresses the problem, but it's not going to scale with the problem space.
It increases in code complexity as I add the various cases and I think that complexity righfully belongs in the controller space, not the model space.

Looking at the code I do see a potential opportunity here though.
Is it possible to create a map containing strings for keys and interfaces for values?  Every value is going to be either
a string literal
an array of strings
another map of string/interfaces

Then just recursively drill through the object and return the value bound to a given label?

Yes you can marshal into a map[string]interface{} http://play.golang.org/p/4SqbLxr_lg

You can of course work on the map[string]interface{} directly, but that would be more annoying.

+ Egon

Benjamin Measures

unread,
Jan 21, 2015, 2:11:59 PM1/21/15
to golan...@googlegroups.com, maxpow...@gmail.com
On Wednesday, 21 January 2015 07:44:16 UTC, maxpow...@gmail.com wrote:
Allowed types in this case references the types of documents the rule applies to since that is a base unit of account. 

I've simplified it to "medical", but in reality it's a huge list.

If this were SQL, it'd look like a new table column for each allowed type.

Why not make permissions an array of pair of allowedtypes and sources?

permissions = [
{
allowedtypes: medical,
sources: {
myself: [*],
mylocation:[r],
other: [a] //(a is a flag meaning that we need to record the fact he accessed it, but otherwise it's open for reading)
}
},
// [...]
]

Reply all
Reply to author
Forward
0 new messages