Android Java: 如何创建POJO并将其转换为可接受的JSON,用于Cloud Firestore REST API。

huangapple go评论106阅读模式
英文:

Android java: How to create POJO and convert it into acceptable JSON for Cloud Firestore REST API

问题

public interface PlaceholderApi {

    @POST("{userId}/documents/{timestamp}")
    Call<Transaction.Result> saveLocationToCloud(
        @Path("userId") String userId,
        @Path("timestamp") long timestamp,
        @Body LocationData data
    );
}

public class NetworkService {

    private static NetworkService instance;

    private static final String WEB_API_KEY = "zaSy..........VWI";

    private static final String BASE_URL_CLOUD
        = "https://firestore.googleapis.com/v1/projects/alocationtracker/databases/(default)/documents/";

    private Retrofit retrofit;

    private NetworkService() {

        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        OkHttpClient.Builder client = new OkHttpClient.Builder()
            .addInterceptor(interceptor);

        client.interceptors().add(chain -> {
            Request request = chain.request();
            HttpUrl url = request.url().newBuilder().addQueryParameter("key", WEB_API_KEY).build();
            request = request.newBuilder().url(url).build();
            return chain.proceed(request);
        });

        retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL_CLOUD)
            .addConverterFactory(GsonConverterFactory.create())
            .client(client.build())
            .build();
    }

    public static NetworkService getInstance() {
        if (instance == null) {
            instance = new NetworkService();
        }
        return instance;
    }

    public PlaceholderApi getJsonApi() {
        return retrofit.create(PlaceholderApi.class);
    }
}

public class LocationData {
    @SerializedName("userId")
    @Expose
    private String userId;

    @SerializedName("timestamp")
    @Expose
    private long timestamp;

    @SerializedName("longitude")
    @Expose
    private ValueWrapper longitude;

    @SerializedName("latitude")
    @Expose
    private ValueWrapper latitude;

    public LocationData(String userId) {
        this.userId = userId;
    }

    public LocationData(String userId, Location location) {
        this.userId = userId;
        this.timestamp = location.getTime();
        this.latitude = new ValueWrapper(location.getLatitude(), "doubleValue");
        this.longitude = new ValueWrapper(location.getLongitude(), "doubleValue");
    }
}

public class ValueWrapper {
    @SerializedName("doubleValue")
    private Double doubleValue;

    @SerializedName("stringValue")
    private String stringValue;

    @SerializedName("integerValue")
    private Integer integerValue;

    public ValueWrapper(Double value, String type) {
        if ("doubleValue".equals(type)) {
            this.doubleValue = value;
        } else if ("stringValue".equals(type)) {
            this.stringValue = String.valueOf(value);
        } else if ("integerValue".equals(type)) {
            this.integerValue = value.intValue();
        }
    }
}
英文:

I made preview test REST API query via postman like this

https://firestore.googleapis.com/v1/projects/MY_PROJECT_ID/databases/(default)/documents/USER_ID_HASH/documents/112233445566

JSON body example:

{
&quot;fields&quot;: {
&quot;longitude&quot;: {
&quot;doubleValue&quot;: 35.5635
},
&quot;latitude&quot;: {
&quot;doubleValue&quot;: 45.5366
}
}
}

And getting http response 200, so going to implement this in code using retrofit2.

The issue is that &quot;doubleValue&quot; is something like field transformation according to value type, so it may be also &quot;stringValue&quot; or &quot;integerValue&quot; for example. And question is how to create POJO class for further converting in JSON body like JSON body example above?

What do I have for now:

API

public interface PlaceholderApi {

@POST(&quot;{userId}/documents/{timestamp}&quot;)
Call&lt;Transaction.Result&gt; saveLocationToCloud(
@Path(&quot;userId&quot;) String userId,
@Path(&quot;timestamp&quot;) long timestamp,
@Body LocationData data
);

}

Network service

public class NetworkService {
private static NetworkService instance;
private static final String WEB_API_KEY = &quot;zaSy..........VWI&quot;;
private static final String BASE_URL_CLOUD
= &quot;https://firestore.googleapis.com/v1/projects/alocationtracker/databases/(default)/documents/&quot;;
private Retrofit retrofit;
private NetworkService() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder client = new OkHttpClient.Builder()
.addInterceptor(interceptor);
client.interceptors().add(chain -&gt; {
Request request = chain.request();
HttpUrl url = request.url().newBuilder().addQueryParameter(&quot;key&quot;, WEB_API_KEY).build();
request = request.newBuilder().url(url).build();
return chain.proceed(request);
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL_CLOUD)
.addConverterFactory(GsonConverterFactory.create())
.client(client.build())
.build();
}
public static NetworkService getInstance() {
if (instance == null) {
instance = new NetworkService();
}
return instance;
}
public PlaceholderApi getJsonApi() {
return retrofit.create(PlaceholderApi.class);
}

}

POJO

public class LocationData {
@SerializedName(&quot;userId&quot;)
@Expose
private String userId;
@SerializedName(&quot;timestamp&quot;)
@Expose
private long timestamp;
@SerializedName(&quot;longitude&quot;)
@Expose
private double longitude;
@SerializedName(&quot;latitude&quot;)
@Expose
private double latitude;
public LocationData(String userId) {
this.userId = userId;
}
public LocationData(String userId, Location location) {
this.userId = userId;
this.timestamp = location.getTime();
this.latitude = location.getLatitude();
this.longitude = location.getLongitude();
}
}

JSON I got with this has incorrect format without value type like &quot;doubleValue&quot; etc.

{&quot;latitude&quot;:19.9802209,&quot;longitude&quot;:16.1852646,&quot;timestamp&quot;:1599830853181,&quot;userId&quot;:&quot;2DBtYfX1uxQszxNmod83&quot;}

I assume POJO class is the only thing I need to change somehow. Or maybe I need to change retrofit.create(PlaceholderApi.class) on something else?

Any suggestions, please.

Thanks.

答案1

得分: 1

如果您从API获得以下响应:

{
  "fields": {
    "longitude": {
      "doubleValue": 35.5635
    },
    "latitude": {
      "doubleValue": 45.5366
    }
  }
}

那么请将您的模型更改为类似以下内容:

public class PlacesResponseModel {

    @SerializedName("fields")
    @Expose
    private Fields fields;

    public Fields getFields() {
        return fields;
    }

    public void setFields(Fields fields) {
        this.fields = fields;
    }

}

public class Fields {

    @SerializedName("longitude")
    @Expose
    private Longitude longitude;
    @SerializedName("latitude")
    @Expose
    private Latitude latitude;

    public Longitude getLongitude() {
        return longitude;
    }

    public void setLongitude(Longitude longitude) {
        this.longitude = longitude;
    }

    public Latitude getLatitude() {
        return latitude;
    }

    public void setLatitude(Latitude latitude) {
        this.latitude = latitude;
    }

}

public class Latitude {

    @SerializedName("doubleValue")
    @Expose
    private Double doubleValue;

    public Double getDoubleValue() {
        return doubleValue;
    }

    public void setDoubleValue(Double doubleValue) {
        this.doubleValue = doubleValue;
    }

}

public class Longitude {

    @SerializedName("doubleValue")
    @Expose
    private Double doubleValue;

    public Double getDoubleValue() {
        return doubleValue;
    }

    public void setDoubleValue(Double doubleValue) {
        this.doubleValue = doubleValue;
    }

}

然后将其添加到类似以下的Retrofit API回调中:

public interface PlaceholderApi {

    @POST("{userId}/documents/{timestamp}")
    Call<PlacesResponseModel> saveLocationToCloud(
        @Path("userId") String userId,
        @Path("timestamp") long timestamp,
        @Body LocationData data
    );
}

最后一步,现在调用它,您应该能够得到已映射的模型。

英文:

If you are getting below response from the API

    {
&quot;fields&quot;: {
&quot;longitude&quot;: {
&quot;doubleValue&quot;: 35.5635
},
&quot;latitude&quot;: {
&quot;doubleValue&quot;: 45.5366
}
}
}

then change your model to something like below.

public class PlacesResponseModel {
@SerializedName(&quot;fields&quot;)
@Expose
private Fields fields;
public Fields getFields() {
return fields;
}
public void setFields(Fields fields) {
this.fields = fields;
}
}
public class Fields {
@SerializedName(&quot;longitude&quot;)
@Expose
private Longitude longitude;
@SerializedName(&quot;latitude&quot;)
@Expose
private Latitude latitude;
public Longitude getLongitude() {
return longitude;
}
public void setLongitude(Longitude longitude) {
this.longitude = longitude;
}
public Latitude getLatitude() {
return latitude;
}
public void setLatitude(Latitude latitude) {
this.latitude = latitude;
}
}
public class Latitude {
@SerializedName(&quot;doubleValue&quot;)
@Expose
private Double doubleValue;
public Double getDoubleValue() {
return doubleValue;
}
public void setDoubleValue(Double doubleValue) {
this.doubleValue = doubleValue;
}
}
public class Longitude {
@SerializedName(&quot;doubleValue&quot;)
@Expose
private Double doubleValue;
public Double getDoubleValue() {
return doubleValue;
}
public void setDoubleValue(Double doubleValue) {
this.doubleValue = doubleValue;
}
}

and add it in the retrofit API callback like below.

public interface PlaceholderApi {
@POST(&quot;{userId}/documents/{timestamp}&quot;)
Call&lt;PlacesResponseModel&gt; saveLocationToCloud(
@Path(&quot;userId&quot;) String userId,
@Path(&quot;timestamp&quot;) long timestamp,
@Body LocationData data
);
}

last step call this now, you should get your models mapped

huangapple
  • 本文由 发表于 2020年9月11日 21:45:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/63848340.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定