简体   繁体   中英

How can I tweak SuperObject library to make it behave case-insensitive?

I just find out the hard way that JSON is case sensitive which means that lWeekRecord['TT_WK_ID'] is not the same as lWeekRecord['tt_wk_id'] (lWeekRecord is an ISuperObject).

I cannot find anything about case sensitivity in the limited SuperObject documentation.

Has anyone ever found/fixed/hacked this; and can tell me how to do that?
I prefer my webservice that receives JSON data to be insensitive to JSON name case.

Edited :

I only need to consume JSON generated by another system, and that only talks to me. I want to be lenient towards the developers of that system. Their JSON is serialized C objects, and I really don't care if they call their vars foo or Foo . Actually, it's worse: parts of their objects are derived from database field names supplied to them, and these even come from different RDBMSes. So this is a chain of dependencies with multiple players involved that can break on something silly as case sensitivity.
If I can avoid that for those people, I want to.
No one in their right mind in that chain is going to use both foo and Foo together (and that would not even be possible in mosts RDMBSes), so I don't have to guard against that.

This isn't really a SuperObject issue. Rather this is a property of JSON itself, which use case-sensitive comparisons.

If you really want to allow your service to be insensitive to letter case, then you'll need to implement the key lookup yourself. Instead of looking up a named value in an object, iterate over all the name/value pairs and perform whatever comparison you wish to do. In pseudo-code it would be something like this:

value := nil;
for name in obj do
  if SameText(name, targetName) then
  begin
    value := obj[name];
    break;
  end;

I would strongly urge you not to do this though. JSON is case sensitive. That's how it is designed and you will find life easier if you go with the flow. Swimming against the tide in this way will surely lead to all sorts of trouble later.

If you have two independent systems talking to each other you need a contract for each message. Just take this sample message:

{
  "foo": "value"
}

In Delphi the names are not case-sensitive but on serialization it does matter.

TMessage = class
  Foo: string;
end;

will generate on serialization

{
  "Foo": "value"
}

which is wrong by the contract.

Flag the field with an attribute to fullfill the contract on serialization

TMessage = class
private
  [SOName('foo')]
  FFoo: string;
public
  property Foo: string read FFoo write FFoo;
end;

Update

Using the attributes allows you the fullfill even worse contracts with mixing upper-lower-case names

TWorseMessage = class
private
  [SOName('foo')]
  FSmallFoo: string;
  [SOName('Foo')]
  FBigFoo: string;
public
  property SmallFoo: string read FSmallFoo write FSmallFoo;
  property BigFoo: string read FBigFoo write FBigFoo;
end;

It is only possible but you should not use it in real production.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM