我在代码中使用jsonschema2pojo时遇到了问题。因此,我使用jsonschema2pojo生成器(http://www.jsonschema2pojo.org/)从以下网址生成POJO:http://store.steampowered.com/api/appdetails/?appids=10
最后,我在一个包'model‘中创建了所有这些类。然后在中,我尝试使用它从链接读取json,但是我收到了异常:
Exception in thread "main" java.lang.NullPointerException
at controller.View.main(View.java:26)我不明白为什么。下面是我如何做的代码:
public class View {
private static String urlStr = "http://store.steampowered.com/api/appdetails/?appids=10";
public static void main(String[] args) {
ObjectMapper objectMapper = new ObjectMapper();
try {
Game game = objectMapper.readValue(new URL(urlStr), Game.class);
System.out.println(game.getData().getName());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}}
Game.class是我在生成器中设置为“类名”的最终类。
怎么啦?我如何从这个链接中获取所有这些数据?
在maven中,我这样配置它:
<plugin>
<groupId>org.jsonschema2pojo</groupId>
<artifactId>jsonschema2pojo-maven-plugin</artifactId>
<version>0.4.18</version>
<configuration>
<sourceType>jsonschema</sourceType>
<outputEncoding>${project.build.sourceEncoding}</outputEncoding>
<outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
<annotationStyle>jackson2</annotationStyle>
<generateBuilders>true</generateBuilders>
<initializeCollections>true</initializeCollections>
</configuration>
<executions>
<execution>
<id>generate-game</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<targetPackage>model.game</targetPackage>
<sourceDirectory>${basedir}/src/main/resources/schema/game</sourceDirectory>
</configuration>
</execution>
</executions>
</plugin>正如我所说的,所有的类都在src/main/java和包'model‘中,我的模式在sr/main/resources/ schema /文件'game’中。
我的模式看起来像这样:
{
"type": "object",
"required":false,
"javaType":"model.Game",
"properties": {
"10": {
"id": "10",
"type": "object",
"properties": {
"success": {
"id": "success",
"type": "boolean"
},
"data": {
"id": "data",
"type": "object",
"properties": {
"type": {
"id": "type",
"type": "string"
},
"name": {
"id": "name",
"type": "string"
},
"steam_appid": {
"id": "steam_appid",
"type": "integer"
},
"required_age": {
"id": "required_age",
"type": "integer"
},
"is_free": {
"id": "is_free",
"type": "boolean"
},
"detailed_description": {
"id": "detailed_description",
"type": "string"
},
"about_the_game": {
"id": "about_the_game",
"type": "string"
},
"supported_languages": {
"id": "supported_languages",
"type": "string"
},
"header_image": {
"id": "header_image",
"type": "string"
},
"website": {
"id": "website",
"type": "null"
},
"pc_requirements": {
"id": "pc_requirements",
"type": "object",
"properties": {
"minimum": {
"id": "minimum",
"type": "string"
}
}
},
"mac_requirements": {
"id": "mac_requirements",
"type": "object",
"properties": {
"minimum": {
"id": "minimum",
"type": "string"
}
}
},
"linux_requirements": {
"id": "linux_requirements",
"type": "object",
"properties": {
"minimum": {
"id": "minimum",
"type": "string"
}
}
},
"developers": {
"id": "developers",
"type": "array",
"items": {
"id": "0",
"type": "string"
}
},
"publishers": {
"id": "publishers",
"type": "array",
"items": {
"id": "0",
"type": "string"
}
},
"price_overview": {
"id": "price_overview",
"type": "object",
"properties": {
"currency": {
"id": "currency",
"type": "string"
},
"initial": {
"id": "initial",
"type": "integer"
},
"final": {
"id": "final",
"type": "integer"
},
"discount_percent": {
"id": "discount_percent",
"type": "integer"
}
}
},
"packages": {
"id": "packages",
"type": "array",
"items": [
{
"id": "0",
"type": "string"
},
{
"id": "1",
"type": "integer"
},
{
"id": "2",
"type": "integer"
},
{
"id": "3",
"type": "integer"
}
]
},
"package_groups": {
"id": "package_groups",
"type": "array",
"items": {
"id": "0",
"type": "object",
"properties": {
"name": {
"id": "name",
"type": "string"
},
"title": {
"id": "title",
"type": "string"
},
"description": {
"id": "description",
"type": "string"
},
"selection_text": {
"id": "selection_text",
"type": "string"
},
"save_text": {
"id": "save_text",
"type": "string"
},
"display_type": {
"id": "display_type",
"type": "integer"
},
"is_recurring_subscription": {
"id": "is_recurring_subscription",
"type": "string"
},
"subs": {
"id": "subs",
"type": "array",
"items": [
{
"id": "0",
"type": "object",
"properties": {
"packageid": {
"id": "packageid",
"type": "string"
},
"percent_savings_text": {
"id": "percent_savings_text",
"type": "string"
},
"percent_savings": {
"id": "percent_savings",
"type": "integer"
},
"option_text": {
"id": "option_text",
"type": "string"
},
"option_description": {
"id": "option_description",
"type": "string"
},
"can_get_free_license": {
"id": "can_get_free_license",
"type": "string"
},
"is_free_license": {
"id": "is_free_license",
"type": "boolean"
},
"price_in_cents_with_discount": {
"id": "price_in_cents_with_discount",
"type": "integer"
}
}
},
{
"id": "1",
"type": "object",
"properties": {
"packageid": {
"id": "packageid",
"type": "integer"
},
"percent_savings_text": {
"id": "percent_savings_text",
"type": "string"
},
"percent_savings": {
"id": "percent_savings",
"type": "integer"
},
"option_text": {
"id": "option_text",
"type": "string"
},
"option_description": {
"id": "option_description",
"type": "string"
},
"can_get_free_license": {
"id": "can_get_free_license",
"type": "string"
},
"is_free_license": {
"id": "is_free_license",
"type": "boolean"
},
"price_in_cents_with_discount": {
"id": "price_in_cents_with_discount",
"type": "integer"
}
}
},
{
"id": "2",
"type": "object",
"properties": {
"packageid": {
"id": "packageid",
"type": "integer"
},
"percent_savings_text": {
"id": "percent_savings_text",
"type": "string"
},
"percent_savings": {
"id": "percent_savings",
"type": "integer"
},
"option_text": {
"id": "option_text",
"type": "string"
},
"option_description": {
"id": "option_description",
"type": "string"
},
"can_get_free_license": {
"id": "can_get_free_license",
"type": "string"
},
"is_free_license": {
"id": "is_free_license",
"type": "boolean"
},
"price_in_cents_with_discount": {
"id": "price_in_cents_with_discount",
"type": "integer"
}
}
},
{
"id": "3",
"type": "object",
"properties": {
"packageid": {
"id": "packageid",
"type": "integer"
},
"percent_savings_text": {
"id": "percent_savings_text",
"type": "string"
},
"percent_savings": {
"id": "percent_savings",
"type": "integer"
},
"option_text": {
"id": "option_text",
"type": "string"
},
"option_description": {
"id": "option_description",
"type": "string"
},
"can_get_free_license": {
"id": "can_get_free_license",
"type": "string"
},
"is_free_license": {
"id": "is_free_license",
"type": "boolean"
},
"price_in_cents_with_discount": {
"id": "price_in_cents_with_discount",
"type": "integer"
}
}
}
]
}
}
}
},
"platforms": {
"id": "platforms",
"type": "object",
"properties": {
"windows": {
"id": "windows",
"type": "boolean"
},
"mac": {
"id": "mac",
"type": "boolean"
},
"linux": {
"id": "linux",
"type": "boolean"
}
}
},
"metacritic": {
"id": "metacritic",
"type": "object",
"properties": {
"score": {
"id": "score",
"type": "integer"
},
"url": {
"id": "url",
"type": "string"
}
}
},
"categories": {
"id": "categories",
"type": "array",
"items": [
{
"id": "0",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"description": {
"id": "description",
"type": "string"
}
}
},
{
"id": "1",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"description": {
"id": "description",
"type": "string"
}
}
}
]
},
"genres": {
"id": "genres",
"type": "array",
"items": {
"id": "0",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "string"
},
"description": {
"id": "description",
"type": "string"
}
}
}
},
"screenshots": {
"id": "screenshots",
"type": "array",
"items": [
{
"id": "0",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "1",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "2",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "3",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "4",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "5",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "6",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "7",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "8",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "9",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "10",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "11",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
},
{
"id": "12",
"type": "object",
"properties": {
"id": {
"id": "id",
"type": "integer"
},
"path_thumbnail": {
"id": "path_thumbnail",
"type": "string"
},
"path_full": {
"id": "path_full",
"type": "string"
}
}
}
]
},
"recommendations": {
"id": "recommendations",
"type": "object",
"properties": {
"total": {
"id": "total",
"type": "integer"
}
}
},
"achievements": {
"id": "achievements",
"type": "object",
"properties": {
"total": {
"id": "total",
"type": "integer"
}
}
},
"release_date": {
"id": "release_date",
"type": "object",
"properties": {
"coming_soon": {
"id": "coming_soon",
"type": "boolean"
},
"date": {
"id": "date",
"type": "string"
}
}
},
"support_info": {
"id": "support_info",
"type": "object",
"properties": {
"url": {
"id": "url",
"type": "string"
},
"email": {
"id": "email",
"type": "string"
}
}
},
"background": {
"id": "background",
"type": "string"
}
}
}
},
"required": [
"success",
"data",
"id",
"path_thumbnail",
"path_full"
]
}
},
"required": [
"10"
]
}有了这个配置,我可以使用下面这一行来读取所有数据,而不是在System.out.println之前:
System.out.println( objectMapper.writeValueAsString( game ) );现在我可以看到完整的json字符串,但是如何使用'game.getData().getName()‘等来读取它呢?
发布于 2015-12-31 08:21:20
您提供的JSON模式将"10“定义为包含其他所有内容的顶级属性。
{
"type": "object",
"required":false,
"javaType":"model.Game",
"properties": {
"10": {
"id": "10",
"type": "object",
"properties": {
"success": {
"id": "success",
"type": "boolean"
},
"data": {
"id": "data",
"type": "object",
"properties": {
"type": {
"id": "type",
"type": "string"
},
"name": {
"id": "name",
"type": "string"
},
...jsonschema2pojo读取该模式并生成一个名为_10的类作为模型的一部分。您可以在generated-sources目录的_10.java中找到它。
@JsonInclude(JsonInclude.Include.NON_NULL)
@Generated("org.jsonschema2pojo")
@JsonPropertyOrder({
"success",
"data"
})
public class _10 {我不知道这是否是在模式中故意的。如果这是故意的,那么您需要像这样访问该名称。
System.out.println(game.get10().getData().getName());在做了这样的更改之后,我能够让它工作起来。
EDIT:似乎这些JSON消息应该有一个变量ID作为包含其他所有内容的顶层键,所以我们需要以不同的方式处理它。我们可以对模式进行泛化,使其不特定于特定的ID,然后我们可以使用两步过程来解析消息。首先,我们将使用ObjectMapper#readValue将整个消息解析为一个Map<String, Object>。我们期望顶级映射将包含一个元素,对应于我们请求的文档的ID,它的值将是一个包含我们感兴趣的值的子映射。然后,我们将通过ObjectMapper#convertValue传递该子映射,以获得所需的Game对象。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cnauroth</groupId>
<artifactId>test-json</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Test JSON</name>
<description>Test JSON</description>
<build>
<plugins>
<plugin>
<groupId>org.jsonschema2pojo</groupId>
<artifactId>jsonschema2pojo-maven-plugin</artifactId>
<version>0.4.18</version>
<configuration>
<sourceType>jsonschema</sourceType>
<outputEncoding>${project.build.sourceEncoding}</outputEncoding>
<outputDirectory>${project.build.directory}/generated-sources/java</outputDirectory>
<annotationStyle>jackson2</annotationStyle>
<generateBuilders>true</generateBuilders>
<initializeCollections>true</initializeCollections>
</configuration>
<executions>
<execution>
<id>generate-game</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<targetPackage>model.game</targetPackage>
<sourceDirectory>${basedir}/src/main/resources/schema/game</sourceDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<mainClass>View</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>${project.artifactId}</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</project>游戏
JSON schema文件太大,无法粘贴,因此这里有一个指向gist的链接。
View.java
import java.net.URI;
import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import model.Game;
public class View {
public static void main(String[] args) throws Exception {
String id = args[0];
URI uri = new URI("http", "store.steampowered.com", "/api/appdetails",
"appids=" + id, null);
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> obj = objectMapper.readValue(uri.toURL(),
new TypeReference<Map<String, Object>>(){});
Game game = objectMapper.convertValue(obj.get(id), Game.class);
System.out.println(game.getData().getName());
}
}演示
> mvn clean package
> java -jar target/test-json.jar 10
Counter-Strike
> java -jar target/test-json.jar 219
Half-Life 2: Demo此外,我还需要对模式进行另一项更改。我删除了linux_requirements属性。这是因为看一下文档10和文档219,前者是一个对象,后者是一个数组。对于文档219,解析器不知道如何理解数组,因为我们需要一个对象。从API返回的数据像这样不一致是很奇怪的。您可能需要对模式进行更多的修改,以使其完全适用于从该API返回的所有可能的JSON文档。
我已经把所有的代码放到了一个GitHub repository中。您可以使用该代码,构建它并运行它来查看它的工作情况。然后,您可以进一步调整它以满足您的需求。
发布于 2016-01-12 03:28:12
使用additionalProperties,而不是尝试使用properties对包含ids的对象进行建模。假设顶级类型包含多个游戏,您可以尝试替换
{
"type": "object",
"required":false,
"javaType":"model.Game",
"properties": {
"10": {
"id": "10",
"type": "object",
...
}
}
}使用类似于
{
"type": "object",
"required":false,
"javaType":"model.Games",
"additionalProperties": {
"id": "game",
"type": "object",
"javaType": "model.Game"
...
}
}这应该会生成一个具有public Map<String, Game> getAdditionalProperties()方法的model.Games类型。
https://stackoverflow.com/questions/34538493
复制相似问题