Search code examples
androidjsongsonretrofitpojo

How to work with retrofit in Android when JSON data is dynamic?


I am making an app that displays daily stock data to the user. The problem is, I am using retrofit to make the API calls. With this type of JSON, I would need a POJO with every stock symbol. This obviously isn't possible. I want to be able to do something along the lines of - listOfStocks[1].getQuote().getLatestPrice();

This is the kind of JSON data that I am receiving.

{  
   "AAPL":{  
      "quote":{  
         "symbol":"AAPL",
         "companyName":"Apple Inc.",
         "primaryExchange":"Nasdaq Global Select",
         "sector":"Technology",
         "calculationPrice":"close",
         "open":156.21,
         "openTime":1548772200635,
         "close":154.68,
         "closeTime":1548795600703,
         "high":158.13,
         "low":154.11,
         "latestPrice":154.68,
         "latestSource":"Close",
         "latestTime":"January 29, 2019",
         "latestUpdate":1548795600703,
         "latestVolume":39402866,
         "iexRealtimePrice":161.04,
         "iexRealtimeSize":90,
         "iexLastUpdated":1548799005088,
         "delayedPrice":154.68,
         "delayedPriceTime":1548795600703,
         "extendedPrice":160.6,
         "extendedChange":5.92,
         "extendedChangePercent":0.03827,
         "extendedPriceTime":1548799199389,
         "previousClose":156.3,
         "change":-1.62,
         "changePercent":-0.01036,
         "iexMarketPercent":0.02338,
         "iexVolume":921239,
         "avgTotalVolume":42308638,
         "iexBidPrice":0,
         "iexBidSize":0,
         "iexAskPrice":0,
         "iexAskSize":0,
         "marketCap":731605928040,
         "peRatio":13.03,
         "week52High":233.47,
         "week52Low":142,
         "ytdChange":-0.030876717325227843
      }
   },
   "FB":{  
      "quote":{  
         "symbol":"FB",
         "companyName":"Facebook Inc.",
         "primaryExchange":"Nasdaq Global Select",
         "sector":"Technology",
         "calculationPrice":"close",
         "open":148,
         "openTime":1548772200837,
         "close":144.19,
         "closeTime":1548795600692,
         "high":148.1,
         "low":143.43,
         "latestPrice":144.19,
         "latestSource":"Close",
         "latestTime":"January 29, 2019",
         "latestUpdate":1548795600692,
         "latestVolume":17353892,
         "iexRealtimePrice":144.25,
         "iexRealtimeSize":100,
         "iexLastUpdated":1548796485236,
         "delayedPrice":144.19,
         "delayedPriceTime":1548795600692,
         "extendedPrice":145.05,
         "extendedChange":0.86,
         "extendedChangePercent":0.00596,
         "extendedPriceTime":1548799197301,
         "previousClose":147.47,
         "change":-3.28,
         "changePercent":-0.02224,
         "iexMarketPercent":0.02505,
         "iexVolume":434715,
         "avgTotalVolume":25773532,
         "iexBidPrice":0,
         "iexBidSize":0,
         "iexAskPrice":0,
         "iexAskSize":0,
         "marketCap":414371435774,
         "peRatio":19.51,
         "week52High":218.62,
         "week52Low":123.02,
         "ytdChange":0.04048110849056598
      }
   },
   "MSFT":{  
      "quote":{  
         "symbol":"MSFT",
         "companyName":"Microsoft Corporation",
         "primaryExchange":"Nasdaq Global Select",
         "sector":"Technology",
         "calculationPrice":"close",
         "open":104.88,
         "openTime":1548772200862,
         "close":102.94,
         "closeTime":1548795600515,
         "high":104.97,
         "low":102.17,
         "latestPrice":102.94,
         "latestSource":"Close",
         "latestTime":"January 29, 2019",
         "latestUpdate":1548795600515,
         "latestVolume":31105047,
         "iexRealtimePrice":102.895,
         "iexRealtimeSize":100,
         "iexLastUpdated":1548795598662,
         "delayedPrice":102.94,
         "delayedPriceTime":1548795600515,
         "extendedPrice":103.67,
         "extendedChange":0.73,
         "extendedChangePercent":0.00709,
         "extendedPriceTime":1548799195514,
         "previousClose":105.08,
         "change":-2.14,
         "changePercent":-0.02037,
         "iexMarketPercent":0.03309,
         "iexVolume":1029266,
         "avgTotalVolume":40670438,
         "iexBidPrice":0,
         "iexBidSize":0,
         "iexAskPrice":0,
         "iexAskSize":0,
         "marketCap":790189956684,
         "peRatio":26.53,
         "week52High":116.18,
         "week52Low":83.83,
         "ytdChange":-0.002371582278481079
      }
   }
}

Solution

  • Personally I'd make a model for quote and symbol then use a Map<String, Symbol>.

    Here's an example where the model only has the latestPrice property to shorten the example:

    class Quote {
         @SerializedName("latestPrice")
         private double latestPrice;
         // ...
    }
    
    class Symbol {
         @SerializedName("quote")
         private Quote quote;
          //...
    }
    

    Now making the Retrofit call use Map<String, Symbol> should give you a map where you can iterate over the entries and get the latest price of each of them.