Add recipe for @FromJson
with non-String input.
This commit is contained in:
parent
2032353ef7
commit
19c41eb18f
3 changed files with 166 additions and 117 deletions
76
README.md
76
README.md
|
@ -132,6 +132,82 @@ Voila:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note that the method annotated with `@FromJson` does not need to take a String as an argument. Rather it can take
|
||||||
|
input of any type and Moshi will first parse the JSON to an object of that type and then use the `@FromJson`
|
||||||
|
method to produce the desired final value. Conversely, the method annotated with `@ToJson` does not have to produce
|
||||||
|
a String.
|
||||||
|
|
||||||
|
Assume, for example, that we have to parse a JSON in which the date and time of an event are represented as two
|
||||||
|
separate strings.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"title": "Blackjack tournament",
|
||||||
|
"begin_date": "20151010",
|
||||||
|
"begin_time": "17:04"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
We would like to combine these two fields into one string to facilitate the date parsing at a
|
||||||
|
later point. That is, while the `EventJson` class corresponds to the JSON structure directly, we would rather
|
||||||
|
have an `Event` that looks like below (while we are at it, we are also changing the variable names to
|
||||||
|
CamelCase).
|
||||||
|
|
||||||
|
```java
|
||||||
|
class EventJson {
|
||||||
|
String title;
|
||||||
|
String begin_date;
|
||||||
|
String begin_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Event {
|
||||||
|
String title;
|
||||||
|
String beginDateAndTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
To enable Moshi to do that transformation automatically we define a class with the `@FromJson`
|
||||||
|
(and `@ToJson`) methods:
|
||||||
|
|
||||||
|
```java
|
||||||
|
class EventJsonAdapter {
|
||||||
|
|
||||||
|
@FromJson
|
||||||
|
Event eventFromJson(EventJson eventJson) {
|
||||||
|
Event event = new Event();
|
||||||
|
event.title = eventJson.title;
|
||||||
|
event.beginDateAndTime = eventJson.begin_date + " " + eventJson.begin_time;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ToJson
|
||||||
|
EventJson eventToJson(Event event) {
|
||||||
|
EventJson json = new EventJson();
|
||||||
|
json.title = event.title;
|
||||||
|
json.begin_date = event.beginDateAndTime.substring(0, 8);
|
||||||
|
json.begin_time = event.beginDateAndTime.substring(9, 14);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And register it with Moshi.
|
||||||
|
|
||||||
|
```java
|
||||||
|
Moshi moshi = new Moshi.Builder()
|
||||||
|
.add(new EventJsonAdapter())
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
We can now use Moshi to parse the JSON directly to an `Event`.
|
||||||
|
|
||||||
|
```java
|
||||||
|
JsonAdapter<Event> jsonAdapter = moshi.adapter(Event.class);
|
||||||
|
Event event = jsonAdapter.fromJson(json);
|
||||||
|
```
|
||||||
|
|
||||||
### Fails Gracefully
|
### Fails Gracefully
|
||||||
|
|
||||||
Automatic databinding almost feels like magic. But unlike the black magic that typically accompanies
|
Automatic databinding almost feels like magic. But unlike the black magic that typically accompanies
|
||||||
|
|
|
@ -1,117 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 Square, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package com.squareup.moshi.recipes;
|
|
||||||
|
|
||||||
import com.squareup.moshi.JsonAdapter;
|
|
||||||
import com.squareup.moshi.JsonReader;
|
|
||||||
import com.squareup.moshi.JsonWriter;
|
|
||||||
import com.squareup.moshi.Moshi;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public final class CustomJsonAdapter {
|
|
||||||
|
|
||||||
public void run() throws Exception {
|
|
||||||
// for some reason our JSON has date and time as separate fields -
|
|
||||||
// we will use a custom JsonAdapter<Event> to clean that up during parsing
|
|
||||||
String json = ""
|
|
||||||
+ "{\n"
|
|
||||||
+ " \"title\": \"Blackjack tournament\",\n"
|
|
||||||
+ " \"beginDate\": \"20151006\",\n"
|
|
||||||
+ " \"beginTime\": \"15:59\"\n"
|
|
||||||
+ "}\n";
|
|
||||||
|
|
||||||
Moshi moshi = new Moshi.Builder()
|
|
||||||
.add(Event.class, new EventAdapter())
|
|
||||||
.build();
|
|
||||||
JsonAdapter<Event> jsonAdapter = moshi.adapter(Event.class);
|
|
||||||
|
|
||||||
Event event = jsonAdapter.fromJson(json);
|
|
||||||
System.out.println(event);
|
|
||||||
System.out.println(jsonAdapter.toJson(event));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
new CustomJsonAdapter().run();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class EventAdapter extends JsonAdapter<Event> {
|
|
||||||
@Override
|
|
||||||
public Event fromJson(JsonReader jsonReader) throws IOException {
|
|
||||||
String title = null;
|
|
||||||
String beginDate = null;
|
|
||||||
String beginTime = null;
|
|
||||||
|
|
||||||
jsonReader.beginObject();
|
|
||||||
while (jsonReader.hasNext()) {
|
|
||||||
String name = jsonReader.nextName();
|
|
||||||
if (name.equals("title")) {
|
|
||||||
title = jsonReader.nextString();
|
|
||||||
} else if (name.equals("beginDate")) {
|
|
||||||
beginDate = jsonReader.nextString();
|
|
||||||
} else if (name.equals("beginTime")) {
|
|
||||||
beginTime = jsonReader.nextString();
|
|
||||||
} else {
|
|
||||||
jsonReader.skipValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jsonReader.endObject();
|
|
||||||
|
|
||||||
final String beginDateAndTime = (beginDate != null) && (beginTime != null) ?
|
|
||||||
beginDate + " " + beginTime : null;
|
|
||||||
|
|
||||||
return new Event(title, beginDateAndTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void toJson(JsonWriter jsonWriter, Event event) throws IOException {
|
|
||||||
jsonWriter.beginObject();
|
|
||||||
|
|
||||||
if (event.title != null) {
|
|
||||||
jsonWriter.name("title");
|
|
||||||
jsonWriter.value(event.title);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.beginDateAndTime != null) {
|
|
||||||
jsonWriter.name("beginDate");
|
|
||||||
jsonWriter.value(event.beginDateAndTime.substring(0, 8));
|
|
||||||
|
|
||||||
jsonWriter.name("beginTime");
|
|
||||||
jsonWriter.value(event.beginDateAndTime.substring(9, 14));
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonWriter.endObject();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Event {
|
|
||||||
public final String title;
|
|
||||||
public final String beginDateAndTime;
|
|
||||||
|
|
||||||
public Event(String title, String beginDateAndTime) {
|
|
||||||
this.title = title;
|
|
||||||
this.beginDateAndTime = beginDateAndTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Event{" +
|
|
||||||
"title='" + title + '\'' +
|
|
||||||
", beginDateAndTime=" + beginDateAndTime +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Square, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.squareup.moshi.recipes;
|
||||||
|
|
||||||
|
import com.squareup.moshi.FromJson;
|
||||||
|
import com.squareup.moshi.JsonAdapter;
|
||||||
|
import com.squareup.moshi.Moshi;
|
||||||
|
import com.squareup.moshi.ToJson;
|
||||||
|
|
||||||
|
public final class FromJsonWithoutStrings {
|
||||||
|
|
||||||
|
public void run() throws Exception {
|
||||||
|
// for some reason our JSON has date and time as separate fields -
|
||||||
|
// we will clean that up during parsing: Moshi will first parse
|
||||||
|
// the JSON directly to an EventJson and from that the EventJsonAdapter
|
||||||
|
// will create the actual Event
|
||||||
|
String json = ""
|
||||||
|
+ "{\n"
|
||||||
|
+ " \"title\": \"Blackjack tournament\",\n"
|
||||||
|
+ " \"begin_date\": \"20151010\",\n"
|
||||||
|
+ " \"begin_time\": \"17:04\"\n"
|
||||||
|
+ "}\n";
|
||||||
|
|
||||||
|
Moshi moshi = new Moshi.Builder()
|
||||||
|
.add(new EventJsonAdapter())
|
||||||
|
.build();
|
||||||
|
JsonAdapter<Event> jsonAdapter = moshi.adapter(Event.class);
|
||||||
|
|
||||||
|
Event event = jsonAdapter.fromJson(json);
|
||||||
|
System.out.println(event);
|
||||||
|
System.out.println(jsonAdapter.toJson(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
new FromJsonWithoutStrings().run();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class EventJson {
|
||||||
|
String title;
|
||||||
|
String begin_date;
|
||||||
|
String begin_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Event {
|
||||||
|
String title;
|
||||||
|
String beginDateAndTime;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Event{" +
|
||||||
|
"title='" + title + '\'' +
|
||||||
|
", beginDateAndTime='" + beginDateAndTime + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class EventJsonAdapter {
|
||||||
|
|
||||||
|
@FromJson
|
||||||
|
Event eventFromJson(EventJson eventJson) {
|
||||||
|
Event event = new Event();
|
||||||
|
event.title = eventJson.title;
|
||||||
|
event.beginDateAndTime = eventJson.begin_date + " " + eventJson.begin_time;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ToJson
|
||||||
|
EventJson eventToJson(Event event) {
|
||||||
|
EventJson json = new EventJson();
|
||||||
|
json.title = event.title;
|
||||||
|
json.begin_date = event.beginDateAndTime.substring(0, 8);
|
||||||
|
json.begin_time = event.beginDateAndTime.substring(9, 14);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue