Add recipe for @FromJson with non-String input.

This commit is contained in:
David Mihola 2015-10-08 09:38:09 +02:00
parent 2032353ef7
commit 19c41eb18f
3 changed files with 166 additions and 117 deletions

View file

@ -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

View file

@ -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 +
'}';
}
}
}

View file

@ -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;
}
}
}