【问题标题】:Convert json structure to array with Retrofit使用 Retrofit 将 json 结构转换为数组
【发布时间】:2014-08-02 23:55:26
【问题描述】:

我遇到了 Retrofit 和 Trakt.tv API 中丑陋的 json 对象的问题:

{
    "season": 1,
    "episodes": {
        "1": true,
        "2": true,
        "3": false,
        "4": false,
        "5": false,
        "6": false,
        "7": false
    }
}

“episodes”内容显然是动态的,我想将其作为一个简单的布尔数组处理,如下所示:

int season;
Boolean[] episodes;

怎么做?

【问题讨论】:

    标签: java gson retrofit


    【解决方案1】:

    您可以先将 JSON 字符串转换为Map<String,Object>,然后最后创建所需的对象。

    示例代码:

    public class EpisodesDetail {
        private int season;
        private Boolean[] episodes;
        // getter & setter 
    }
    ...
    
    BufferedReader reader = new BufferedReader(new FileReader(new File("json.txt")));
    Type type = new TypeToken<Map<String, Object>>() {}.getType();
    Map<String, Object> map = new Gson().fromJson(reader, type);
    
    EpisodesDetail geometry = new EpisodesDetail();
    geometry.setSeason(((Double) map.get("season")).intValue());
    geometry.setEpisodes(((Map<String, Boolean>) map.get("episodes")).values().toArray(
            new Boolean[] {}));
    
    System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(geometry));
    

    输出:

    {
      "season": 1,
      "episodes": [
        true,
        true,
        false,
        false,
        false,
        false,
        false
      ]
    }
    

    还有另一种方法使用GSON Deserialiser

    示例代码:

    class EpisodesDetailDeserializer implements JsonDeserializer<EpisodesDetail> {
    
        @Override
        public EpisodesDetail deserialize(final JsonElement json, final Type typeOfT,
                final JsonDeserializationContext context) throws JsonParseException {
    
            EpisodesDetail geometry = new EpisodesDetail();
            JsonObject jsonObject = json.getAsJsonObject();
            int season = jsonObject.get("season").getAsInt();
            geometry.setSeason(season);
    
            List<Boolean> episodes = new ArrayList<Boolean>();
            Set<Entry<String, JsonElement>> set = jsonObject.get("episodes").getAsJsonObject()
                    .entrySet();
    
            Iterator<Entry<String, JsonElement>> it = set.iterator();
            while (it.hasNext()) {
                episodes.add(it.next().getValue().getAsBoolean());
            }
            geometry.setEpisodes(episodes.toArray(new Boolean[] {}));
            return geometry;
        }
    }
    
    BufferedReader reader = new BufferedReader(new FileReader(new File("json.txt")));
    EpisodesDetail episodesDetail = new GsonBuilder()
            .registerTypeAdapter(EpisodesDetail.class, new EpisodesDetailDeserializer())
            .create().fromJson(reader, EpisodesDetail.class);
    
    System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(episodesDetail));
    

    How do I write a custom JSON deserializer for Gson?

    【讨论】:

      【解决方案2】:

      当我使用jackson 库来解析该JSON 时,我使用ObjectMapperDramaInfo 类,如下所示。

      package jackson;
      
      import java.io.IOException;
      import java.util.LinkedList;
      import java.util.List;
      import java.util.Map;
      import java.util.stream.Collectors;
      
      import com.fasterxml.jackson.databind.ObjectMapper;
      
      class DramaInfo {
      
          int season;
          List<Boolean> episodes;
      
      
          public void setSeason(int season) {
              this.season = season;
          }
          public int getSeason() {
              return this.season;
          }
      
          public List<Boolean> getEpisodes() {
              return new LinkedList<>( this.episodes );
          }
          public void setEpisodes(Map<String, Boolean> o) {
              // used Java 1.8 Stream.
              // just see http://docs.oracle.com/javase/tutorial/collections/streams/reduction.html
              episodes = o.keySet().stream().map(e -> o.get(e)).collect(Collectors.toList());
          }
      
          public String toString() {
              String ret = "season: " + this.season + "\n";
              ret += this.episodes.toString();
              return ret;
          }
      }
      
      public class LoadJsonData {
      
          public static void main(String[] args) {
              String toConvert = "{\"season\": 1, \"episodes\": { \"1\": true, \"2\": true, \"3\": false, \"4\": false, \"5\": false, \"6\": false, \"7\": false } }";
              ObjectMapper mapper = new ObjectMapper();
              try {
                  DramaInfo info = mapper.readValue(toConvert, DramaInfo.class);
                  System.out.println(info);
              } catch (IOException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
              }
          }
      }
      

      所以,这是一个建议,因为我从未使用过 Retrofit。如果你要像下面这样使用 Retrofit,试试上面的DramaInfo 类怎么样?

      public interface DramaService {
        @GET("/dramas/{drama}/info")
        DramaInfo listRepos(@Path("drama") String drama);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-09
        • 2013-05-15
        • 2021-08-02
        • 1970-01-01
        • 2015-06-22
        相关资源
        最近更新 更多