Opened 11 years ago

Closed 10 years ago

Last modified 10 years ago

#5906 closed enhancement (wontfix)

[patch][cla]Represent hashes in dojo.objectToQuery

Reported by: guest Owned by: James Burke
Priority: high Milestone: future
Component: Core Version: 1.0
Keywords: xhr, ajax, post, object, Cc: yazad3@…
Blocked By: Blocking:

Description (last modified by James Burke)

In order to be able to post AJAX queries like this:

eID=tx_t3dojo_model&tx_t3dojo_type=t3dojo_grid&tx_t3dojo[t3dojo_query_connector]=test_connector&tx_t3dojo[command]=info

a javascript parameter with sub objects needs to be converted correctly

var param =  {
              eID: this.eID,
              tx_t3dojo: {
                      t3dojo_query_connector: this.T3DojoQueryConnector
              }
        };

The change below would do the trick:

dojo.objectToQuery = function(/*Object*/ map){


        var ec = encodeURIComponent;
        var ret = "";
        var backstop = {};
        for(var x in map){
            if(map[x] != backstop[x]){
                if(_d.isArray(map[x])){
                    for(var y=0; y<map[x].length; y++){
                        ret += ec(x) + "=" + ec(map[x][y]) + "&";
                    }
                } /*change achim gerber */ else if(_d.isObject(map[x])){
                    for(var y in map[x]){
                        ret += ec(x) + "[" + ec(y) + "]" + "=" + ec(map[x][y]) + "&";
                    }
                } /* end change achim gerber */else{
                    ret += ec(x) + "=" + ec(map[x]) + "&";
                }
            }
        }
        if(ret.length && ret.charAt(ret.length-1) == "&"){
            ret = ret.substr(0, ret.length-1);
        }
        return ret; // String
    }

Greetings - Achim

Change History (18)

comment:1 Changed 11 years ago by Adam Peller

Milestone: 1.0.3
Owner: changed from anonymous to James Burke
Summary: problems with dojo.objectToQuery[patch][cla]Represent hashes in dojo.objectToQuery
Type: defectenhancement

changed summary to be more descriptive (did I get it right?) wouldn't queryToObject need to support the inverse mapping? does this follow the url query convention of any particular software, or is this something new?

it would be great if you could submit patches as diffs in the future. unit tests are a plus, too.

comment:2 Changed 11 years ago by dylan

Milestone: 1.1

comment:3 Changed 11 years ago by James Burke

I can apply this patch, but favor changing the serialization so that instead of doing this:

ob[propName1]=value1&obj[propName2]=value2

it will be doing this:

ob["propName1"]=value1&obj["propName2"]=value2

Note the inclusion of double quotes inside the brackets. Actually, the brackets and double quotes will be URL encoded to %5B/%5D and %22 respectively if you look at the raw HTTP request.

In the absence of a standard for serializing object properties to URL parameters (or did I miss something?), I'm favoring using the JSON/JavaScript approach of using double quotes around the property name.

Hmm, actually, come to think of it, I'm not sure we should be doing this at all: an equally valid escaping could be using straight JSON for the object:

obj={"propName1":"value1","propName2":"value2"}

Of course the obj value above would be URL encoded. This has the added value of supporting nested objects.

Can anyone provide info on any standards in this area? I'm reticent to code something unless we have a solid precedent. What do other JS libraries do, or do they even try?

I will likely close this as wontfix unless we have solid evidence of a generally accepted standard.

comment:4 Changed 11 years ago by Adam Peller

Milestone: 1.11.2

comment:5 Changed 11 years ago by James Burke

Description: modified (diff)
Resolution: wontfix
Status: newclosed

No further comments on any accepted standards for object to URL parameter conversion. So closing as wontfix. Feel free to re-open if there is a generally accepted standard.

comment:6 in reply to:  5 Changed 10 years ago by yaz_k83

Resolution: wontfix
Status: closedreopened

Hi jburke/peller,

First of all great follow up on the ticket. I appreciate that. Since there seems to be no consensus on the treatment of nested objects, why not provide a hook for developers to override themselves.

The content attribute can be a JSON of different shapes and sizes. This JSON can be intepreted by different server side technologies differently. Current objectToQuery is very rigid and expects the object to follow a particular format - that is so not Dojo! :)

So how about in the xhr arguments we look for a hook first - contentToQueryHook (I am bad at naming :( ) which is a reference to a function who's signature needs to accept a JSON, and returns a query string.

So to implement it,

  1. xhr will now be passed an additional argument contentToQueryHook .
  2. If this function is present the dojo._ioSetArgs calls that function or calls the plain old objectToQuery.
  3. Thats it.

This approach will give us flexibility to plug in different content management hooks for different calls if needed. Please consider this. Thank you.

Regards, Yazad Khambata

Replying to jburke:

No further comments on any accepted standards for object to URL parameter conversion. So closing as wontfix. Feel free to re-open if there is a generally accepted standard.

comment:7 Changed 10 years ago by yaz_k83

Please add me in cc on this ticket - yazad3@… i should be able to help with the fix.

Regards, Yazad Khambata yazad3@…

comment:8 in reply to:  7 Changed 10 years ago by yaz_k83

Yazad3 at G Mail dot com

comment:9 Changed 10 years ago by James Burke

Cc: yazad3@… added
Milestone: 1.2future

It seems easier for you just overwrite the definition of dojo.objectToQuery() with your preferred implementation for your specific app/use case? I am not sure we need to provide hooks for it.

If you think that will work for you, then I will close out the ticket.

comment:10 Changed 10 years ago by yaz_k83

Hi jbruke,

I think this is a much needed feature especially for Dojo.... Eventually most project using Dojo will need this. Take a case of editable grids, what if the changed rows need to be sent back to the server, thay cant be pure maps they would be an array of objects... Data of tree nodes wouldnt be simple maps again.

Overriding objectToQuery would be simple but not the cleanest approach, hope you agree...

Do you have a better way of approaching the issue? If yes i'd love to discuss, but i personally fell a content handler is a much needed featur thats a miss in the API.

Thank you...

Regards, Yazad khambata

comment:11 Changed 10 years ago by Eugene Lazutkin

To me it looks like a specific case rather than a general solution => it is the application-level functionality, not the library-level one.

The candidate to the core functionality suitable for a library should satisfy one of two criteria:

  1. Implement commonly used code patterns. In this case we minimize the code duplication across multiple applications as well as in a single application.
  2. Hide the differences between platforms (e.g., browsers) by providing a unified interface to the required functionality. In this case we help to write cross-platform applications and eliminate extra code like in (1) above.

IMHO the proposed functionality fails on both accounts, while the "flat" attribute mapping (already implemented by Dojo) is supported by most server-side frameworks.

comment:12 Changed 10 years ago by James Burke

In the XHR calls, you can avoid the objectToQuery calls by passing postData: "string of data to put in the HTTP body" and call dojo.rawXhrPost (or use putData with dojo.rawXhrPut).

So I still don't see the need for a custom serialization routine: it seems like if the developer need something very custom, the developer would set the HTTP body directly using the properties/methods above. I think we need to do a bit more work to make that a bit more standard for the base dojo.xhr method, but I prefer to just skip the serialization that the dojo.xhr* methods do and have the developer use their custom serialization before calling the dojo.xhr* call.

comment:13 in reply to:  12 Changed 10 years ago by yaz_k83

Hi jbruke,

What i am discussing is not necessarily a case for request body of Put or Post, this is a valid case for request parameters. Data withing editable grid data would not find their place in the request body but in request parameters.

We have several cases within Dojo where the controls do not communicate in flat structures that can be utilized by the xhr method in a way that doesn't require special server side processing. Request parameters are popular on server side for more than one reason. Sending JSONs to the server is NOT always an option, for starters the server needs to be JSON aware, which may not always be a technical limitation but for security reasons may be kept deliberately agnostic to JSONs, and Markups sent from a remote client. Besides you may have cases where server side code is not in your control and you need to communicate with multiple servers all having different standards for communication in that case overriding the objectToQuery will be futile and unmanageable.

Adding this much needed hook will provide developers with the ability to define how the request parameters must be created based on their requirement and sever abilities.

I agree with your idea of putting the request body of put and post to better use but i feel that may not always be feasible.

Hooks provide a clean way to do what is need rather than overriding functions.

I was only suggesting a possible solution to the problem since we are in a similar situation and i saw this ticket which simply got closed as a wont fix since there wasn't any consensus on the on the conversion strategy.

Please feel free to take a call on this ticket... you may close it as a wont fix if you wish; in case you are planning to incorporate it, let me know i can help with the patch and test cases. Thank you.

Regards, Yazad Khambata

Replying to jburke:

In the XHR calls, you can avoid the objectToQuery calls by passing postData: "string of data to put in the HTTP body" and call dojo.rawXhrPost (or use putData with dojo.rawXhrPut).

So I still don't see the need for a custom serialization routine: it seems like if the developer need something very custom, the developer would set the HTTP body directly using the properties/methods above. I think we need to do a bit more work to make that a bit more standard for the base dojo.xhr method, but I prefer to just skip the serialization that the dojo.xhr* methods do and have the developer use their custom serialization before calling the dojo.xhr* call.

comment:14 in reply to:  11 Changed 10 years ago by yaz_k83

Hi Elazutkin,

Thanks, but personally i feel,

  1. sending complex data structures from client to the server is not uncommon. If it is, it's simply because alternatives are unavailable.
  1. While working with enterprise applications browser isn't the only platform who's differences and compatibilities matter (especially when we are discussing xhr). Enterprise solutions demand transfer in various forms even within the same protocol! For example consider a high end portal developed to integrate various legacy systems.

Making assumptions about the servers ability/limitations in that case may not always be an option. And for all you know the developer may use the hook to simply "flatten" complex data before it is sent to a server!

Regards, Yazad Khamabta

Replying to elazutkin:

To me it looks like a specific case rather than a general solution => it is the application-level functionality, not the library-level one.

The candidate to the core functionality suitable for a library should satisfy one of two criteria:

  1. Implement commonly used code patterns. In this case we minimize the code duplication across multiple applications as well as in a single application.
  2. Hide the differences between platforms (e.g., browsers) by providing a unified interface to the required functionality. In this case we help to write cross-platform applications and eliminate extra code like in (1) above.

IMHO the proposed functionality fails on both accounts, while the "flat" attribute mapping (already implemented by Dojo) is supported by most server-side frameworks.

comment:15 Changed 10 years ago by James Burke

Resolution: wontfix
Status: reopenedclosed

Yazad, thank you for the thoughtful replies. However, I still do not see this as a common enough need. As you say, there are other components in Dojo/Dijit/Dojox? that have more complicated communication mechanisms, but none of them needed this capability.

Maybe over time this will make more sense, but to date it does not seem common enough to warrant the extra overhead in Dojo Base.

comment:16 in reply to:  15 Changed 10 years ago by yaz_k83

Thank you Jbruke and Elazutkin for your time and insight on the issue.

Regards,
Yazad Khambata

Replying to jburke:

Yazad, thank you for the thoughtful replies. However, I still do not see this as a common enough need. As you say, there are other components in Dojo/Dijit/Dojox? that have more complicated communication mechanisms, but none of them needed this capability.

Maybe over time this will make more sense, but to date it does not seem common enough to warrant the extra overhead in Dojo Base.

comment:17 Changed 10 years ago by Nick Fenwick

I see this ticket has been marked wontfix due to lack of interest. I'd like to vote for this change to be considered for dojo core, though you're free to ignore me :) I'm using dojo.back to save meaningful bookmarks of my ajax application state, and would like an easy way to encode a 'state object' into the URL. e.g.

http://myapp/index.html#state=<encoded object goes here>

For example, saving a complex search looks like:

var searchData = {
  field1: 'value1',
  complexField: {
    complexF1: 'stuff',
    complexF2: 'nonsense
  }
};
dojo.back.addToHistory( new MyBackData(dojo.objectToQuery(searchData)));

With current dojo 1.3.2, I cannot use dojo.objectToQuery in order to stash this object in the URL, and thus make my complex search bookmarkable. I have to break the object into a flat object, and re-expand later.

I see this as an 'interesting' requirement, and separate from the earlier arguments that typical dojo.xhr usage invalidates this change request.

comment:18 Changed 10 years ago by James Burke

neek, I suggest using encodeURIComponent(dojo.toJson(searchData)) for your needs.

Note: See TracTickets for help on using tickets.