Benutzung von JsonPath-Funktionen min und max

Hi!

Folgender code wird von der URL geliefert.

{
"tick":[419.94,418.97,419.88,419.08,419.96]
}

min($.tick[*]) sollte laut JsonPath doku den kleinsten wert liefern. Was es auch tut, wenn man json und min() hier testet. http://jsonpath.herokuapp.com/

Ist das eher ein PP oder JsonPath problem?

Die verwendete JsonPath-Bibliothek kann nicht alles, und ich bin auch nicht sicher, welche Version davon gerade in PP steckt. (Und sie hat keine Übersicht, was seit welcher Version geht.)

Habe gerade mal kurz geschaut: es wird die aktuelle JsonPath-Version 2.7.0 in PP verwendet, allerdings laufen Funktionen wie min(), length(), etc. aufgrund der implementierten Konfiguration in einen Fehler:
com.jayway.jsonpath.JsonPathException: Options AS_PATH_LIST and ALWAYS_RETURN_LIST are not allowed when using path functions!

5 Likes

Danke für die schnelle Antwort. Der Hinweis ist gut.
Das ist die Stelle: GenericJSONQuoteFeed.java#L205
Es wird dafür gesortgt, dass immer ein List<Object> von JsonPath.read() zurückgegeben wird.

Wäre sowas alternativ denkbar. Ich bin nicht so fit mit sauberem Code oder Programmier-style. :sweat_smile:

diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/online/impl/GenericJSONQuoteFeed.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/online/impl/GenericJSONQuoteFeed.java
--- name.abuchen.portfolio/src/name/abuchen/portfolio/online/impl/GenericJSONQuoteFeed.java
+++ name.abuchen.portfolio/src/name/abuchen/portfolio/online/impl/GenericJSONQuoteFeed.java
@@ -192,8 +192,19 @@
 
         return Optional.of(prices.get(prices.size() - 1));
     }
 
+    protected List<Object> alternateRead(ReadContext ctx, JsonPath jpExpression) {
+        try {
+            float rf = ctx.read(jpExpression);
+            List<Object> rl;
+            rl.add(rf);
+        } catch (JsonPathException e) {
+            List<Object> rl = ctx.read(jpExpression);
+        }
+        return rl;
+    }
+
     protected List<LatestSecurityPrice> parse(String url, String json, String datePath, String closePath,
                     QuoteFeedData data, Optional<String> dateFormat, Optional<String> lowPath,
                     Optional<String> highPath, Optional<String> volumePath)
     {
@@ -206,28 +217,28 @@
                             .addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL);
 
             ReadContext ctx = JsonPath.parse(json, configuration);
 
-            List<Object> dates = ctx.read(dateP);
-            List<Object> close = ctx.read(closeP);
+            List<Object> dates = alternateRead(ctx,dateP);
+            List<Object> close = alternateRead(ctx,closeP);
 
             Optional<List<Object>> high = Optional.empty();
             Optional<List<Object>> low = Optional.empty();
             Optional<List<Object>> volume = Optional.empty();
             if(highPath.isPresent())
             {
                 JsonPath highP = JsonPath.compile(highPath.get());
-                high = Optional.of(ctx.read(highP));
+                high = Optional.of(alternateRead(ctx,highP));
             }
             if(lowPath.isPresent())
             {
                 JsonPath lowP = JsonPath.compile(lowPath.get());
-                low = Optional.of(ctx.read(lowP));
+                low = Optional.of(alternateRead(ctx,lowP));
             }
             if(volumePath.isPresent())
             {
                 JsonPath volumeP = JsonPath.compile(volumePath.get());
-                volume = Optional.of(ctx.read(volumeP));
+                volume = Optional.of(alternateRead(ctx,volumeP));
             }
 
             if (dates.size() != close.size())
             {

Du könntest einen Pull Request erstellen und versuchen Andreas davon zu überzeugen :wink:
Dafür wäre es sicherlich hilfreich, eine Beschreibung des Use-Case mit aufzunehmen.

Ich habe Deinen Code jetzt nicht getestet, aber ich persönlich finde die Variante über die JsonPathException nicht so elegant. Ggfs. sollte man eher prüfen, ob man diese JsonPath-Optionen nicht verändern kann.

1 Like

Sollte es nicht $.tick.min() bzw $.tick.max() heißen?

Das funktioniert genauso (bzw. ganauso nicht in PP). Ich habe meine Variante aus diesem Thread hier: Aggregation function attempted to calculate value using empty array · Issue #191 · json-path/JsonPath · GitHub
Das Problem ist aber wie dev-investor gezeigt hat, das JsonPath in PP mit der Option ALWAYS_RETURN_LIST konfiguriert wird.

Ja, die Variante ist auch nicht elegant. Ich muss bei Gelegenheit mal die IDE aufsetzten. Dazu war ich zu Faul ich entwickle nicht aktiv in java und habe nichts parat. Es war mir dann nicht wichtig genug “min” und “max” für meinen Kurs zu haben. Was dann auch der UseCase wäre. Aus einer JSON Kursquelle die z.B. für einen Tag ein Array von preisen zurück gibt, relativ einfach mit min() und max() vom Tageskurs eben diese Werte zu füllen. Bei meinem patch habe ich auch das eigentliche vergessen, nämlich das deaktivieren von ALWAYS_RETURN_LIST in Zeile 205.

Tatsächlich war mein erster Ansatz ein typenloses Objekt zu definieren und dann abzufragen, welchen typ ich bekommen habe. Dafür reichen meine java kenntnisse spontan nicht aus.
Ich muss mal schauen, wenn ich mehr Zeit habe setze ich die IDE auf und gehe mal an das Thema dran. Wenn es genug interesse findet.
Ich muss mich ohnehin mal mehr mit Git auseinandersetzen. Stichwort pull request.

Beispiel UseCase:
grafik