- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
如何使用 Gson 这个 url 解析这个 json 对象: http://apis.skplanetx.com/weather/forecast/3hours?appKey=4ce0462a-3884-30ab-ab13-93efb1bc171f&version=1&lon=127.9259&lat=36.991
"wind": {
"wdir3hour": "176.00",
"wspd3hour": "3.10",
"wdir4hour": "",
"wspd4hour": "",
"wdir1hour": "173.00",
"wspd1hour": "3.60",
"wdir2hour": "175.00",
"wspd2hour": "3.40"
},
"precipitation": {
"sinceOntime1hour": "0.00",
"type1hour": "0",
"sinceOntime2hour": "0.00",
"type2hour": "0",
"sinceOntime3hour": "0.00",
"type3hour": "0",
"sinceOntime4hour": "",
"type4hour": ""
},
我如何为这个 json 对象编写 java 模型。我不想写变量每个都这样归档。
class Wind{
@SerializedName("wdir1hour")
private String wdir1hour;
@SerializedName("wdir2hour")
private String wdir2hour;
@SerializedName("wdir3hour")
private String wdir3hour;
@SerializedName("wdir4hour")
private String wdir4hour;
}
谁对这个 json 对象有更好的想法??
最佳答案
可通过您提供的链接访问的当前 JSON 响应似乎存在一些设计问题或怀疑。为了不让它在将来丢失,我将在这里发布 JSON:
{
"weather": {
"forecast3hours": [
{
"grid": {
"city": "충북",
"county": "충주시",
"village": "목행동",
"latitude": "37.0135600000",
"longitude": "127.9036500000"
},
"lightning1hour": "0",
"timeRelease": "2017-02-24 16:30:00",
"wind": {
"wspd2hour": "3.10",
"wdir1hour": "179.00",
"wspd1hour": "4.20",
"wdir2hour": "176.00",
"wdir3hour": "",
"wspd3hour": "",
"wdir4hour": "",
"wspd4hour": ""
},
"precipitation": {
"sinceOntime1hour": "0.00",
"type1hour": "0",
"sinceOntime2hour": "0.00",
"type2hour": "0",
"sinceOntime3hour": "",
"type3hour": "",
"sinceOntime4hour": "",
"type4hour": ""
},
"sky": {
"code1hour": "SKY_V01",
"name1hour": "맑음",
"code2hour": "SKY_V01",
"name2hour": "맑음",
"code3hour": "",
"name3hour": "",
"code4hour": "",
"name4hour": ""
},
"temperature": {
"temp1hour": "3.20",
"temp2hour": "2.00",
"temp3hour": "",
"temp4hour": ""
},
"humidity": {
"rh1hour": "41.00",
"rh2hour": "50.00",
"rh3hour": "",
"rh4hour": ""
},
"lightning2hour": "0",
"lightning3hour": "",
"lightning4hour": ""
}
]
},
"common": {
"alertYn": "N",
"stormYn": "N"
},
"result": {
"code": 9200,
"requestUrl": "/weather/forecast/3hours?lon=127.9259&lat=36.991&version=1&appKey=4ce0462a-3884-30ab-ab13-93efb1bc171f",
"message": "성공"
}
}
在我看来他们是:
null
的空字符串值而不是 null
s 或只是从响应中排除。Yn
后缀,并定义 true
和 false
使用 "Y"
和 "N"
分别。这就是为什么自动 POJO 生成器可能不是处理它的最佳方法,因为它们可能无法检测特定 JSON 字符串值的“真实”类型,而且它们无法生成自定义反序列化器。不确定为什么要这样设计,但您可以设计自定义映射,使其在编程上更加友好,并能更好地控制它们。
final class Response {
final Weather weather = null;
final Common common = null;
final Result result = null;
@Override
public String toString() {
return new StringBuilder("Response{")
.append("weather=").append(weather)
.append(", common=").append(common)
.append(", result=").append(result)
.append('}').toString();
}
}
final class Weather {
final List<Forecast> forecast3hours = null;
@Override
public String toString() {
return new StringBuilder("Weather{")
.append("forecast3hours=").append(forecast3hours)
.append('}').toString();
}
}
final class Forecast {
final Grid grid;
final Date timeRelease;
final List<Integer> lightnings;
final List<Wind> winds;
final List<Precipitation> precipitations;
final List<Sky> skies;
final List<Float> temperatures;
final List<Float> humidities;
Forecast(final Grid grid, final Date timeRelease, final List<Integer> lightnings, final List<Wind> winds, final List<Precipitation> precipitations,
final List<Sky> skies, final List<Float> temperatures, final List<Float> humidities) {
this.grid = grid;
this.timeRelease = timeRelease;
this.lightnings = lightnings;
this.winds = winds;
this.precipitations = precipitations;
this.skies = skies;
this.temperatures = temperatures;
this.humidities = humidities;
}
@Override
public String toString() {
return new StringBuilder("Forecast{")
.append("grid=").append(grid)
.append(", timeRelease=").append(timeRelease)
.append(", lightnings=").append(lightnings)
.append(", winds=").append(winds)
.append(", precipitations=").append(precipitations)
.append(", skies=").append(skies)
.append(", temperatures=").append(temperatures)
.append(", humidities=").append(humidities)
.append('}').toString();
}
}
final class Grid {
final String city = null;
final String county = null;
final String village = null;
final double latitude = Double.valueOf(0); // disable inlining the primitive double 0
final double longitude = Double.valueOf(0); // disable inlining the primitive double 0
@Override
public String toString() {
return new StringBuilder("Grid{")
.append("city='").append(city).append('\'')
.append(", county='").append(county).append('\'')
.append(", village='").append(village).append('\'')
.append(", latitude=").append(latitude)
.append(", longitude=").append(longitude)
.append('}').toString();
}
}
final class Wind {
final float speed;
final float direction;
Wind(final float speed, final float direction) {
this.speed = speed;
this.direction = direction;
}
@Override
public String toString() {
return new StringBuilder("Wind{")
.append("speed=").append(speed)
.append(", direction=").append(direction)
.append('}').toString();
}
}
final class Precipitation {
final float sinceOntime;
final int type;
Precipitation(final float sinceOntime, final int type) {
this.sinceOntime = sinceOntime;
this.type = type;
}
@Override
public String toString() {
return new StringBuilder("Precipitation{")
.append("sinceOntime='").append(sinceOntime).append('\'')
.append(", type=").append(type)
.append('}').toString();
}
}
final class Sky {
final String code;
final String name;
Sky(final String code, final String name) {
this.code = code;
this.name = name;
}
@Override
public String toString() {
return new StringBuilder("Sky{")
.append("code='").append(code).append('\'')
.append(", name='").append(name).append('\'')
.append('}').toString();
}
}
final class Common {
@SerializedName("alertYn")
@JsonAdapter(YnToBooleanJsonDeserializer.class)
final boolean alert = Boolean.valueOf(false); // disable inlining the primitive boolean false
@SerializedName("stormYn")
@JsonAdapter(YnToBooleanJsonDeserializer.class)
final boolean storm = Boolean.valueOf(false); // disable inlining the primitive boolean false
@Override
public String toString() {
return new StringBuilder("Common{")
.append("alert=").append(alert)
.append(", storm=").append(storm)
.append('}').toString();
}
}
final class Result {
final int code = Integer.valueOf(0); // disable inlining the primitive int 0
final String requestUrl = null;
final String message = null;
@Override
public String toString() {
return new StringBuilder("Result{")
.append("code=").append(code)
.append(", requestUrl='").append(requestUrl).append('\'')
.append(", message='").append(message).append('\'')
.append('}').toString();
}
}
其中一些映射具有显式构造函数——此类对象必须在自定义反序列化器中手动实例化。如果没有提供构造函数,那么 Gson 可以处理这种映射本身,只要有足够的关于应该如何反序列化特定对象的信息。
由于数据应该以非标准方式解析,因此可以实现几个自定义反序列化器。以下类型的适配器转换 "Y"
和 "N"
至 true
和 false
分别。
final class YnToBooleanJsonDeserializer
implements JsonDeserializer<Boolean> {
// Gson will instantiate this adapter itself
private YnToBooleanJsonDeserializer() {
}
@Override
public Boolean deserialize(final JsonElement jsonElement, final Type type, final JsonDeserializationContext context)
throws JsonParseException {
final String rawFlag = jsonElement.getAsString();
switch ( rawFlag ) {
case "N":
return false;
case "Y":
return true;
default:
throw new JsonParseException("Can't parse: " + rawFlag);
}
}
}
下一个JsonDeserializer
试图检测 xxx<N>hour
-like 带有正则表达式的键并提取 <N>
索引构建构建 Forecast
所需的列表实例。请注意,它可以解析任意大小的“列表”(JSON 中的列表)。
final class ForecastJsonDeserializer
implements JsonDeserializer<Forecast> {
// This deserializer does not hold any state and can be instantiated once per application life-cycle.
private static final JsonDeserializer<Forecast> forecastJsonDeserializer = new ForecastJsonDeserializer();
private ForecastJsonDeserializer() {
}
static JsonDeserializer<Forecast> getForecastJsonDeserializer() {
return forecastJsonDeserializer;
}
@Override
public Forecast deserialize(final JsonElement jsonElement, final Type type, final JsonDeserializationContext context)
throws JsonParseException {
final JsonObject jsonObject = jsonElement.getAsJsonObject();
return new Forecast(
context.deserialize(jsonObject.get("grid"), Grid.class),
context.deserialize(jsonObject.get("timeRelease"), Date.class),
lightningsExtractor.parseList(jsonObject),
windsExtractor.parseList(jsonObject.get("wind").getAsJsonObject()),
precipitationsExtractor.parseList(jsonObject.get("precipitation").getAsJsonObject()),
skiesExtractor.parseList(jsonObject.get("sky").getAsJsonObject()),
temperaturesExtractor.parseList(jsonObject.get("temperature").getAsJsonObject()),
humiditiesExtractor.parseList(jsonObject.get("humidity").getAsJsonObject())
);
}
private static final AbstractExtractor<Integer> lightningsExtractor = new AbstractExtractor<Integer>(compile("lightning(\\d)hour")) {
@Override
protected Integer parse(final int index, final JsonObject jsonObject) {
final String rawLightning = jsonObject.get("lightning" + index + "hour").getAsString();
if ( rawLightning.isEmpty() ) {
return null;
}
return parseInt(rawLightning);
}
};
private static final AbstractExtractor<Wind> windsExtractor = new AbstractExtractor<Wind>(compile("(?:wdir|wspd)(\\d)hour")) {
@Override
protected Wind parse(final int index, final JsonObject jsonObject) {
String rawSpeed = jsonObject.get("wspd" + index + "hour").getAsString();
String rawDirection = jsonObject.get("wdir" + index + "hour").getAsString();
if ( rawSpeed.isEmpty() && rawDirection.isEmpty() ) {
return null;
}
return new Wind(parseFloat(rawSpeed), parseFloat(rawDirection));
}
};
private static final AbstractExtractor<Precipitation> precipitationsExtractor = new AbstractExtractor<Precipitation>(compile("(?:sinceOntime|type)(\\d)hour")) {
@Override
protected Precipitation parse(final int index, final JsonObject jsonObject) {
final String rawSinceOntime = jsonObject.get("sinceOntime" + index + "hour").getAsString();
final String rawType = jsonObject.get("type" + index + "hour").getAsString();
if ( rawSinceOntime.isEmpty() && rawType.isEmpty() ) {
return null;
}
return new Precipitation(parseFloat(rawSinceOntime), parseInt(rawType));
}
};
private static final AbstractExtractor<Sky> skiesExtractor = new AbstractExtractor<Sky>(compile("(?:code|name)(\\d)hour")) {
@Override
protected Sky parse(final int index, final JsonObject jsonObject) {
final String rawCode = jsonObject.get("code" + index + "hour").getAsString();
final String rawName = jsonObject.get("name" + index + "hour").getAsString();
if ( rawCode.isEmpty() && rawName.isEmpty() ) {
return null;
}
return new Sky(rawCode, rawName);
}
};
private static final AbstractExtractor<Float> temperaturesExtractor = new AbstractExtractor<Float>(compile("temp(\\d)hour")) {
@Override
protected Float parse(final int index, final JsonObject jsonObject) {
final String rawTemperature = jsonObject.get("temp" + index + "hour").getAsString();
if ( rawTemperature.isEmpty() ) {
return null;
}
return parseFloat(rawTemperature);
}
};
private static final AbstractExtractor<Float> humiditiesExtractor = new AbstractExtractor<Float>(compile("rh(\\d)hour")) {
@Override
protected Float parse(final int index, final JsonObject jsonObject) {
final String rawHumidity = jsonObject.get("rh" + index + "hour").getAsString();
if ( rawHumidity.isEmpty() ) {
return null;
}
return parseFloat(rawHumidity);
}
};
private abstract static class AbstractExtractor<T> {
private final Pattern pattern;
private AbstractExtractor(final Pattern pattern) {
this.pattern = pattern;
}
protected abstract T parse(int index, JsonObject jsonObject);
private List<T> parseList(final JsonObject jsonObject) {
final List<T> list = new ArrayList<>();
for ( final Entry<String, JsonElement> e : jsonObject.entrySet() ) {
final String key = e.getKey();
final Matcher matcher = pattern.matcher(key);
// Check if the given regular expression matches the key
if ( matcher.matches() ) {
// If yes, then just extract and parse the index
final int index = parseInt(matcher.group(1));
// And check if there is enough room in the result list because the JSON response may contain unordered keys
while ( index > list.size() ) {
list.add(null);
}
// As Java lists are 0-based
if ( list.get(index - 1) == null ) {
// Assuming that null marks an object that's probably not parsed yet
list.set(index - 1, parse(index, jsonObject));
}
}
}
return list;
}
}
}
现在一切都可以放在一起了:
public static void main(final String... args) {
final Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd hh:mm:ss")
.registerTypeAdapter(Forecast.class, getForecastJsonDeserializer())
.create();
final Response response = gson.fromJson(JSON, Response.class);
System.out.println(response);
}
输出:
Response{weather=Weather{forecast3hours=[Forecast{grid=Grid{city='충북', county='충주시', village='목행동', latitude=37.01356, longitude=127.90365}, timeRelease=Fri Feb 24 16:30:00 EET 2017, lightnings=[0, 0, null, null], winds=[Wind{speed=4.2, direction=179.0}, Wind{speed=3.1, direction=176.0}, null, null], precipitations=[Precipitation{sinceOntime='0.0', type=0}, Precipitation{sinceOntime='0.0', type=0}, null, null], skies=[Sky{code='SKY_V01', name='맑음'}, Sky{code='SKY_V01', name='맑음'}, null, null], temperatures=[3.2, 2.0, null, null], humidities=[41.0, 50.0, null, null]}]}, common=Common{alert=false, storm=false}, result=Result{code=9200, requestUrl='/weather/forecast/3hours?lon=127.9259&lat=36.991&version=1&appKey=4ce0462a-3884-30ab-ab13-93efb1bc171f', message='성공'}}
关于java - Android中如何根据动态SerializedName用gson解析json对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42433276/
通常,我使用@SerializedName批注来映射JSON字段。但是,在Google Architecture Component示例项目中,我看到它们使用了@field:SerializedNam
我制作了一个 Bean 类,但是当我运行它时,这会出错。我不知道我该如何解决它。请帮我。 Error:(7, 8) error: cannot find symbol class Serialize
在我的 Android 应用程序中,我定义了太多模型类,并且使用了大写属性名称,如下所示: public String FirstName; public String LastName; 使用此命名
我可以从配置文件等中获取@SerializedName值吗? 我的意思是: @SerializedName(value = configProfider.getJsonFieldName()) pri
在使用 Proguard 的项目中,minifyEnabled true 在使用 Gson 时未正确解析 ApiError 类。 data class ApiResponse( @Serial
我有一个正在序列化以发出请求的对象。 private static final String JSON_REQUEST_ID = "requestId"; private static final S
我有一个 json,我在 Realm 模型中使用 gson 通过注释 @SerializedName 进行转换。 但有时在 json 中,有一个未知的键,我想将其序列化为字符串。 public cla
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 5 年前。 Improve th
我的服务有问题,因为同一字段在请求和响应中的形式不同,因此我使用 @Expose 注释来序列化一个并反序列化另一个: @SerializedName("photo") @Expose(deserial
我正在使用 Retrofit 并且根据 json 有很多 pojo 类。因为我正在使用 Gson 解析,所以我需要使用: @SerializedName("home") private List ho
我有一个包含以下代码的数据类 data class MyBody( @SerializedName("ver") val version: Int, @SerializedName("
Gson 中有没有办法将多个 JSON 字段映射到单个 Java 对象成员变量? 假设我有一个 Java 类... public class MyClass { String id;
不幸的是,我从中提取的 JSON 文件有一个具有相同变量名称的节点,但可能随机具有两种不同的数据类型。当我进行网络调用(使用 gson)时,出现错误: com.google.gson.JsonSynt
我正在使用 com.google.gson.annotations.SerializedName 以及 gson 文档中提到的元素“value”和“alternate”@SerializedName(
我正在根据我的目的改编我在网上找到的一些代码。它正在获取具有列名称(例如“william_henry_harrison”)但使用本地名称(例如“Tippecanoe”)的数据: public clas
这是我使用 Gson 进行序列化的第一种方法。我收到 facebook 对我的 android 应用程序的响应,如下所示: Result: { Response: resp
我有一个带有一些 GSon 注释的 DTO。 我的问题是,如果我的应用程序在开发、暂存或生产中运行,这些注释的值必须改变... 目前,我必须用不同的值打包我的应用程序,我希望它是自动的...它在 Sp
所以我正在尝试使用 Moshi 解析来 self 的服务器的调用。这是我的响应对象。 public class TokenResponse { @SerializedName("accessT
我有这样一个类: class A { @Expose @SerializedName("a_id") private String id; } 现在我想创建扩展 A 的类 B,
关于 Gson,@Expose 和 @SerializedName("stringValue") 有什么区别? 最佳答案 即使为时已晚,我也想回答这个问题。要解释它我们必须知道什么是serializa
我是一名优秀的程序员,十分优秀!