jsonschema2pojo с URL не работает

У меня проблемы с использованием jsonschema2pojo в моем коде. Поэтому я использую генератор jsonschema2pojo ( http://www.jsonschema2pojo.org/) для генерации POJO по этому адресу: http://store.steampowered.com/api/appdetails/?appids=10

Наконец, я создаю все эти классы в одном пакете 'модель'. Затем я пытаюсь использовать его для чтения 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()' и т. Д.?

2 ответа

Предоставленная вами схема 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 как часть модели. Вы можете найти это в _10.java в каталоге сгенерированных источников.

@JsonInclude(JsonInclude.Include.NON_NULL)
@Generated("org.jsonschema2pojo")
@JsonPropertyOrder({
    "success",
    "data"
})
public class _10 {

Я не знаю, было ли это намеренно в схеме. Если это преднамеренно, то вам нужно будет получить доступ к имени, как это.

System.out.println(game.get10().getData().getName());

Я смог заставить его работать после внесения этого изменения.

РЕДАКТИРОВАТЬ: Кажется, что эти сообщения JSON, как ожидается, будут иметь идентификатор переменной в качестве ключа верхнего уровня, содержащего все остальное, поэтому нам нужно обрабатывать это немного по-другому. Мы можем обобщить схему так, чтобы она не была привязана к конкретному идентификатору, и затем мы можем использовать двухэтапный процесс для анализа сообщения. Во-первых, мы будем использовать [ObjectMapper#readValue] ( https://fasterxml.github.io/jackson-databind/javadoc/2.5/com/fasterxml/jackson/databind/ObjectMapper.html, com.fasterxml.jackson.core.type.TypeReference)) для разбора всего сообщения в Map<String, Object>, Мы ожидаем, что карта верхнего уровня будет содержать один элемент, соответствующий идентификатору запрошенного нами документа, и его значением будет подкарта, содержащая интересующие нас значения. Затем мы передадим эту подкарту. через [ObjectMapper#convertValue] ( https://fasterxml.github.io/jackson-databind/javadoc/2.5/com/fasterxml/jackson/databind/ObjectMapper.html, java.lang.Class)), чтобы получить 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 слишком большой для вставки, поэтому здесь есть ссылка на суть.

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, могут быть такими непоследовательными. Возможно, вам придется еще немного поработать со схемой, чтобы она полностью работала для всех возможных документов JSON, возвращаемых из этого API.

Я поместил весь код в репозиторий GitHub. Вы можете взять этот код, собрать его и запустить, чтобы увидеть, как он работает. Затем вы можете адаптировать его к вашим потребностям.

Вместо того, чтобы пытаться смоделировать объект, содержащий идентификаторы с propertiesиспользовать additionalProperties, Предполагая, что тип верхнего уровня содержит несколько игр, вы можете попробовать заменить

{
  "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"
      ...
  }
}

Это должно сделать model.Games введите с помощью метода, как public Map<String, Game> getAdditionalProperties(),

Другие вопросы по тегам