0

Update Datensätze aus API Response

Hallo Forum,

 

ich brauche mal wieder Hilfe weil ich selbst mich verbissen habe und  nicht weiter komme.

Folgendes Problem:

Ich habe eine Tabelle zu einem Wertpapiere X, einen Kurswert Y und ein Datum/Zeit enthält. Mit einem JSON API Aufruf frage ich nun für die Wertpapiere den aktuellen Kurswert aus einem Server ab. Zurück bekomme ich eine folgende Nachricht:

{"result":{"Wertpapier 1":{"usd":1.23},"Wertpapier 2":{"usd":234.12},"Wertpapier 3":{"usd":4.67}}}

Bis dahin alles OK. Doch bei dem Versuch, den String nach Wertpapier und Betrag aufzusplitten und jeweils mit dem aktuellen Datum/Uhrzeit in die oben genannte Tabelle einen Datensatz mit Wertpapier X, Kurswert Y, Datum/Zeit,  anzuhängen, scheitere ich.

Könnt Ihr mir helfen?

Vielen Dank!

4 Antworten

null
    • UweG
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Mir ist keine Möglichkeit bekannt, um mit Ninox eigenen Mitteln die JSON-Object Keys auszulesen.
    Es besteht aber die Möglichkeit mit einem inoffiziellem Hack daran zu kommen.
    Mit diesem Hack bekommt man die Möglichkeit JavaScript direkt in Ninox auszuführen.

    Grundlage dafür ist ein Funktionsfeld, welches folgendes Script enthält:
    Script von Jacques TUR
     

    html("
    <script>
        debugger;
        //get the address of the Eval function of NinoxScript
        var evalFunctor = queries.getFunctor('eval', [{ sign: function () { return 'string' } }, { sign: function () { return 'nid' } }]);
    
        //get the execution context of the NinoxScripts
        var Ctx = new queries.JSRuntimeContext();
    
        //setting up the hook function
        if (evalFunctor && Ctx /* && !evalFunctor.oldFunction*/) {
            //save the old eval function, the one with the parameters eval(string,nid)
            if (evalFunctor.argTypes[0] == 'string') {
                evalFunctor.oldFunction = Ctx.F[evalFunctor.functorId];
            }
    
    
            //initialization of new parameter types: eval(any,any)
            evalFunctor.argTypes[0] = 'any';
            evalFunctor.argTypes[1] = 'any';
            evalFunctor.sign = 'eval(any,any)';
    
            //creation of the new extended function table
            evalFunctor.exFunctions = {};
    
            //add extended functions to the array
            evalFunctor.exFunctions['exEvalJS'] = exEvalJS;
            evalFunctor.exFunctions['exComments'] = exComments;
    
            /*
                Implementation of the new function eval in the Ninox functions array.
                Now the eval function can be called in two ways.
                1 - In the case of a call to the original eval function:
    
                    fnt: Ninox code to be evaluated.
                    params: Current record (this) which will be used as a context to evaluate the fnt code.
    
                2 - In the case of a call to the extended functions:
                    fnt: string that contains either the name of the extended function.
                    params : object which contains the parameters of the extended functions call.
    
                in both cases :
                    db : database object.
                    ret : function to call at the end of the function. The functions are called by stacking. When the first one is finished, it calls the next one.
    
                */
    
            evalFunctor.hook = function (fnt, params, db, ret) {
    
                try {
                    //search if the first parameter of the eval function strictly contains the name of an extended function
                    if (evalFunctor.exFunctions[fnt]) {
                        //if this is the case, the corresponding function is called
                        evalFunctor.exFunctions[fnt](fnt, params, db, ret);
                    } else {
                        //If not, the Ninox function is called
                        evalFunctor.oldFunction(fnt, params, db, ret);
                    }
                } catch (err) {
                    //in case of an error, the error message is returned through the 'ret' return function
                    ret(String(err.message));
                }
            };
    
            //recording the hooked function in the NinoxScript function array
            Ctx.F[evalFunctor.functorId] = evalFunctor.hook;
        }
    
        //returns the record id from its number or from the record object
        function getId(record) {
            if (typeof record === 'string') return record;
            else if (typeof record === 'object') return record._id;
            else return null;
        }
    
        /*
        extended function that allows the execution of JavaScript code
        eval('exEvalJS', {javascript:, arguments:{param1:, param2:...}})
            javascript : string that contains the code to be executed
            arguments : {
                        param1,
                        param2… : parameters passed to the code as arguments to a function
                        }
    
        return : result of JavaScript fonction.
    
        exemple :eval('exEvalJS', {
                                    javascript: 'return a + b;'',
                                    arguments : {
                                                a: 10,
                                                b: 20
                                                }
                                });
        result -> 30;
    
        important: for an asynchronous function, call cb('return value') rather than return 'return value'
    
            exemple : promise.then( (value) => {
                                                cb(value);
                                                } ).then();
    
        */
        function exEvalJS(fnt, params, db, cb) {
    
            try {
                debugger;
                var { javascript, arguments } = params;
                var head = `var {${Object.keys(arguments).join(',')}} = args;`;
                var all = head + '\n' + javascript;
                var fn = Function('args', 'cb', all,);
                try {
                    var Result = fn(arguments, cb);
                    //check if function use CallBack to return result asynchronously
                    if (javascript.search(/\b(cb)\b/) < 0)
                        return cb(Result);
                } catch (err) {
                    var msgErr =
                        err.message + ' à la ligne ' + err.line - 2 + ', colonne ' + err.column;
                    return cb(err)
                }
            } catch (err) {
                var msgErr =
                    err.message + 'exEvalJS : à la ligne ' + err.line + ', colonne ' + err.column;
    
                cb(msgErr);
            }
        }
    
        /*
        getting the list of comments of a record
        eval('exComments', {id:} )
        return array of JSON with :
            comment : string of comment,
            userId : id of user post the comment,
            date : date of post in milli seconde.
    
        exemple : eval('exComments', {id:this.id});
        result -> {comment:... ,userId:..., date:167533002 }
        */
        function exComments(fnt, params, db, cb) {
    
            database.loadComments(getId(params.id), function (error, commentsArray) {
                if (error)
                    cb('exComments : ' + error);
                else {
                    var commentsList = [];
                    for (num in commentsArray) {
                        var o = {
                            comment: commentsArray[num][2],
                            userId: commentsArray[num][1],
                            date: new Date(commentsArray[num][0]),
                        };
                        commentsList.push(o);
                    }
    
                    cb(commentsList);
                }
            });
        }
    </script>
    ")
    

    Dieses Funktionsfeld muss einmalig nach dem Start von Ninox aufgerufen werden.

    Dann kann man mit folgender Funktion die Namen der im JSON enthaltenen Object-Keys auslesen:
    Script in ein Funktionsfeld zum Testen kopieren.
     

    eval("exEvalJS", {
        javascript: "return Object.keys(a);",
        arguments: {
            a: {
                result: {
                    FreizeitAktie: {
                        usd: 1.23
                    },
                    HochHinaus: {
                        usd: 234.12
                    },
                    'Glückauf': {
                        usd: 4.67
                    }
                }
            }.result
        }
    })
    

    Da mir auch kein Weg bekannt ist, wie man ein JSON-Object über Variablennamen auswerten kann habe ich das mal mit dem JavaScript-Hack weiter gebaut.

    Anbei eine Beispieldatenbank, die dein Response in eine Tabelle schreibt.
    Inwieweit, es bei neuen Ninox-Updates funktioniert, muss man testen.
    Mit der neuen 3.7.0 läuft es jedenfalls.

    • Leonid_Semik.2
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Oh, je. Das ist aber eine Menge Code.
    Ich würde zuerst aber damit versuchen:
     

    let myRes := Response.result;
    let myText := formatJSON(myRes);
    let myLength := length(myText);
    myText := substr(myText, 1, myLength - 2);
    let myArray := split(myText, ",");
    let myNamesArray := for i in myArray do
            replace(first(split(text(i), ":")), """", "")
        end;
    for i in myNamesArray do
        let new := (create Wertpapiere);
        new.(Wertpapier := i);
        new.(Zeitpunkt := now());
       new.(Kurswert := item(myRes, i).usd)
    end

    Leo

      • UweG
      • vor 2 Jahren
      • Gemeldet - anzeigen

      Leonid Semik Ich verneige mich und habe wieder etwas dazu gelernt.

    • Frank.7
    • vor 2 Jahren
    • Gemeldet - anzeigen

    Hallo Leo,

    ... immer wieder beeindruckend!!!

    Nachdem ich nun x Zeilen Code geschrieben habe und es doch nur bis zum Update der Datensätze in der Tabelle reichte, kommst Du mit so ein paar lächerlichen Zeilen Code und es funktioniert auf Anhieb perfekt. 

    Ich ziehe abermals meinen Hut auf's Neue vor Dir !!!

    Vielen Dank!

    Und natürlich auch vielen Dank an Uwe - auch wenn es hier mit der Lösung von Leo schneller ist, kann man das Script von Dir vlt. doch an anderer Stelle brauchen...

Content aside

  • vor 2 JahrenZuletzt aktiv
  • 4Antworten
  • 264Ansichten
  • 3 Folge bereits