Java 和 json 对象

标签 java json jackson

我正在尝试从链接下载包含最新新闻的 JSON 文件,然后使用 JSON 文件中的新闻文章填充新闻页面,但我无法让它工作。

这是我的 JSON 文件:

[
"sections": {
  {
    "title": "category 1",
    "color": 2,
    "posts": [
      {
        "title": "Test 1",
        "date": 17-09-2019,
        "images": {
          "launcher_preview": "testimage.png",
          "imageName2": "testimage.png"
        },
        "href": "https://testlink.com"
      },
      {
        "title": "Test 2",
        "date": 17-09-2019,
        "images": {
          "launcher_preview": "testimage2.png",
          "imageName2": "testiamge2.png"
        },
        "href": "https://testlink2.com"
      }
    ]
  },
  {
    "title": "category 2",
    "color": 2,
    "posts": [
      {
        "title": "Test 3",
        "date": 17-09-2019,
        "images": {
          "launcher_preview": "testimage3.png",
          "imageName2": "testimage3.png"
        },
        "href": "https://testlink3.com"
      }
    ]
  }
  }

]

我的java类(仅包含必要的部分):

public class NewsFeedManager extends ImageCache {
private static final String METADATA_URL = "https://Linkhiddenforprivacy.com/news/latest.json",
        IMAGE_PROVIDER_URL = "https://Linkhiddenforprivacy.com/news/images/";

private static final int CACHE_TIME = 1000 * 60 * 20;

private final ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());

@JsonProperty
@Getter
private NewsFeed feed = new NewsFeed();

private Path imageCacheDir;

public NewsFeedManager() {

}

public static NewsFeedManager load(Launcher launcher) {
    NewsFeedManager manager = Persistence.load(new File(launcher.getCacheDir(), "news_feed.json"), NewsFeedManager.class);
    manager.imageCacheDir = Paths.get(launcher.getCacheDir().getAbsolutePath(), "launcher/news/images");

    return manager;
}

public ListenableFuture<NewsFeed> refresh(boolean force) {
    if (!force && this.feed != null && this.feed.expires > System.currentTimeMillis()) {
        return Futures.immediateFuture(this.feed);
    }

    ListenableFuture<NewsFeed> future = this.executor.submit(() -> {
        log.info("Fetching latest news feed from " + METADATA_URL);

        NewsFeed feed = HttpRequest.get(HttpRequest.url(METADATA_URL))
                .execute()
                .expectResponseCode(200)
                .returnContent()
                .asJson(NewsFeed.class);

        feed.expires = System.currentTimeMillis() + CACHE_TIME;

        return feed;
    });

    Futures.addCallback(future, new FutureCallback<NewsFeed>() {
        @Override
        public void onSuccess(@Nullable NewsFeed result) {
            NewsFeedManager.this.feed = result;
            NewsFeedManager.this.save();
        }

        @Override
        public void onFailure(Throwable t) {
            t.printStackTrace();
        }
    });

    return future;
}

public ListenableFuture<Image> getImage(String resource) {
    String remote = IMAGE_PROVIDER_URL + resource;
    log.info("Fetching latest image feed from " + remote);

    return this.obtain(resource, remote, false);
}

private void save() {
    Persistence.commitAndForget(this);
}

public void clear() {
    this.feed = null;

    this.clearImageCache();
}

@Override
protected long getMaxCacheTime() {
    return CACHE_TIME;
}

@Override
protected Path getImageCacheFolder() {
    return this.imageCacheDir;
}

public static class NewsFeed {
    @JsonProperty
    @Getter
    private List<NewsSection> sections;

    @JsonProperty
    private long expires;
}

public static class NewsSection {
    @JsonProperty
    @Getter
    private String title;

    @JsonProperty
    @Getter
    private int color;

    @JsonProperty
    @JsonManagedReference
    @Getter
    private List<NewsPost> posts;
}

public static class NewsPost {
    @JsonProperty
    @Getter
    private String title;

    @JsonProperty
    @Getter
    private Date date;

    @JsonProperty
    @Getter
    private Map<String, String> images;

    @JsonProperty
    @Getter
    private String href;

    @JsonBackReference
    @Getter
    private NewsSection section;
}

当客户端尝试获取新闻时,我收到此错误:

    [info] Fetching latest news feed from https://linkhiddenforprivacy.com/news/latest.json
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.hiddenforprivacy.launcher.ui.resources.NewsFeedManager$NewsFeed out of START_ARRAY token
 at [Source: java.io.StringReader@4ac13260; line: 1, column: 1]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:691)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:685)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromArray(BeanDeserializerBase.java:1215)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:126)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2986)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2091)
    at com.skcraft.launcher.util.HttpRequest$BufferedResponse.asJson(HttpRequest.java:479)
    at com.hiddenforprivacy.launcher.ui.resources.NewsFeedManager.lambda$refresh$0(NewsFeedManager.java:61)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

我不确定是什么导致了这个错误,我认为我的 JSON 格式不正确,但我不确定,这里有人能看到是什么导致了这个错误吗?

感谢您的宝贵时间, 皮特

最佳答案

如果您的对象位于数组中,则无法为其分配键。因此,您的 HttpRequest.asJson() 失败。我已经编辑了您的 JSON,以将您的部分作为对象数组返回,而不是包含这些部分的单个数组对象。

此外,JSON 文件中不能将日期作为数字。我也将它们转换为字符串。出于标准化目的,请确保将日期存储为 ISO 8601实际文件中的字符串。

尝试一下 JSON 的编辑版本:

[
  {
      "title": "category 1",
      "color": 2,
      "posts": [{
              "title": "Test 1",
              "date": "17-09-2019",
              "images": {
                  "launcher_preview": "testimage.png",
                  "imageName2": "testimage.png"
              },
              "href": "https://testlink.com"
          },
          {
              "title": "Test 2",
              "date": "17-09-2019",
              "images": {
                  "launcher_preview": "testimage2.png",
                  "imageName2": "testiamge2.png"
              },
              "href": "https://testlink2.com"
          }
      ]
  },
  {
      "title": "category 2",
      "color": 2,
      "posts": [{
          "title": "Test 3",
          "date": "17-09-2019",
          "images": {
              "launcher_preview": "testimage3.png",
              "imageName2": "testimage3.png"
          },
          "href": "https://testlink3.com"
      }]
  }
]

关于Java 和 json 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57977753/

相关文章:

java - 如何动态添加JButton到JPanel?

java - 合并 Cesium 和 Ozone Widget Framework

java - 我可以使用 logback 或其他方式登录到单独的 Eclipse 控制台吗?

java - Jersey 对象映射

php - 如何访问数组中的json?

java - 当 ReSTLet 应该返回 400 Bad Request 时,它是否返回 415 Unsupported Media Type?

json - getOutputStream() 已经被称为 spring boot

java - 在运行时和编译时计算字符串

java - 我怎样才能在java中浏览这个json?

java - 如何添加和忽略 json 响应的字段