Re formatting JSON data to fit into tree store

2019-06-21 21:39发布

I want to make Nested list of shopping categories using data provided by server which looks something like this:

{
    "status":{"statusCode":15001},
    "data":[
        {"itemId":1, "name":"Men", "subCategories":[
            {"itemId":2, "name":"Clothes", "subCategories":[
                {"itemId":3, "name":"Formals", "leaf":true,"subCategories":[]},
                {"itemId":4, "name":"Casual", "leaf":true,"subCategories":[]},
                {"itemId":5, "name":"Sports", "leaf":true,"subCategories":[]}
            ]},
            {"itemId":6, "name":"Accessories", "subCategories":[
                {"itemId":7, "name":"Formals", "leaf":true,"subCategories":[]},
                {"itemId":8, "name":"Casual", "leaf":true,"subCategories":[]},
                {"itemId":9, "name":"Sports", "leaf":true,"subCategories":[]}
            ]}
        ]},
        {"itemId":10, "name":"Women", "subCategories":[
            {"itemId":11, "name":"Clothes", "subCategories":[
                {"itemId":12, "name":"Formals", "leaf":true,"subCategories":[]},
                {"itemId":13, "name":"Casual", "leaf":true,"subCategories":[]},
                {"itemId":14, "name":"Ethnic", "leaf":true,"subCategories":[]}
            ]},
            {"itemId":15, "name":"Shoes", "subCategories":[
                {"itemId":16, "name":"Hells", "leaf":true,"subCategories":[]},
                {"itemId":17, "name":"Wedges", "leaf":true,"subCategories":[]},
                {"itemId":18, "name":"Sports", "leaf":true,"subCategories":[]}
            ]}
        ]}
    ]
}

Since tree structure is wrapped in data element and children are wrapped in subCategories tag which is different from data so I wanted to pre-process this data such that it can be used by Nested List directly by making response like this:

{
    "categories":[
        {"itemId":1, "name":"Men", "categories":[
            {"itemId":2, "name":"Clothes", "categories":[
                {"itemId":3, "name":"Formals", "leaf":true,"categories":[]},
                {"itemId":4, "name":"Casual", "leaf":true,"categories":[]},
                {"itemId":5, "name":"Sports", "leaf":true,"categories":[]}
            ]},
            {"itemId":6, "name":"Accessories", "categories":[
                {"itemId":7, "name":"Formals", "leaf":true,"categories":[]},
                {"itemId":8, "name":"Casual", "leaf":true,"categories":[]},
                {"itemId":9, "name":"Sports", "leaf":true,"categories":[]}
            ]}
        ]},
        {"itemId":10, "name":"Women", "categories":[
            {"itemId":11, "name":"Clothes", "categories":[
                {"itemId":12, "name":"Formals", "leaf":true,"categories":[]},
                {"itemId":13, "name":"Casual", "leaf":true,"categories":[]},
                {"itemId":14, "name":"Ethnic", "leaf":true,"categories":[]}
            ]},
            {"itemId":15, "name":"Shoes", "categories":[
                {"itemId":16, "name":"Hells", "leaf":true,"categories":[]},
                {"itemId":17, "name":"Wedges", "leaf":true,"categories":[]},
                {"itemId":18, "name":"Sports", "leaf":true,"categories":[]}
            ]}
        ]}
    ]
}

For this I was overriding getResponseData of reader but this method never gets called and no records are loaded in store. What am I doing wrong?

Here is my store:

Ext.define('MyTabApp.store.CategoriesStore',{
    extend:'Ext.data.TreeStore',
    config:{
        model   : 'MyTabApp.model.Category',
        autoLoad: false,
        storeId : 'categoriesStore',
        proxy: {
            type: 'ajax',
            url: Properties.CONFIG_SERVICE_BASE_URL+'topnav/getall',
            reader: {
                type: 'json',
                getResponseData: function(response) {
                    console.log("in getResponseData"); // Never logged in console
                    var rText = response.responseText;
                    var processed = Helper.replaceAll("data","categories",rText);
                    processed = Helper.replaceAll("subCategories","categories",processed);
                    var respObj = Ext.JSON.decode(processed);
                    return respObj.categories;
                }
            }
        },
        listeners:{
            load: function( me, records, successful, operation, eOpts ){ 
                console.log("categories tree loaded");
                console.log(records); // This prints blank array
            }
        }
    }
});

and here is model:

Ext.define('MyTabApp.model.Category', {
    extend : 'Ext.data.Model',
    config : {
        idProperty  : 'itemId',
        fields      : [ 
           {name : 'itemId',type : 'int'}, 
           {name : 'name',type : 'string'}
        ]
    }
});

This is the list:

Ext.define('MyTabApp.view.CategoriesList', {
    extend: 'Ext.dataview.NestedList',
    alias : 'widget.categorieslist',
    config: {
        height              : '100%',
        title               : 'Categories',
        displayField        : 'name',
        useTitleAsBackText  : true,
        style               : 'background-color:#999 !important; font-size:75%',
        styleHtmlContent    : true,
        listConfig: {
            itemHeight: 47,
            itemTpl : '<div class="nestedlist-item"><div style="position:absolute; left:10px; top:10px; color:#222; font-size:130%">{name}</div></div>',
            height : "100%"
        }
    },
    initialize : function() {
        this.callParent();
        var me = this;

        var catStore = Ext.create('MyTabApp.store.CategoriesStore');
        catStore.load();
        me.setStore(catStore);
    }
});

What is best practice to process & format received data if it is not in the format we want and we don't have control over services?

1条回答
萌系小妹纸
2楼-- · 2019-06-21 22:04

I dont think you can attach getResponseData to reader's configuration. In past I have used the following approach.

  1. Create an override of Ext.data.reader.Json like below. But the downside is that this will be called for all your proxies using json reader. and then add YourApp.override.data.reader.Json in the requires section of your application.

    Ext.define('YourApp.override.data.reader.Json', { override: 'Ext.data.reader.Json', 'getResponseData': function(response) { // your implementation here }

  2. Alternatively you can make a Ext.Ajax.request and on success handler parse the data the way you want and then set the data in your store. You can also write this code in the "refresh" event or "beforeload" event of the store and return false to cancel the action

查看更多
登录 后发表回答