在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:square/moshi开源软件地址:https://github.com/square/moshi开源编程语言:Kotlin 60.1%开源软件介绍:MoshiMoshi is a modern JSON library for Android, Java and Kotlin. It makes it easy to parse JSON into Java and Kotlin classes: Note: The Kotlin examples of this README assume use of either Kotlin code gen or JavaString json = ...;
Moshi moshi = new Moshi.Builder().build();
JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class);
BlackjackHand blackjackHand = jsonAdapter.fromJson(json);
System.out.println(blackjackHand); Kotlinval json: String = ...
val moshi: Moshi = Moshi.Builder().build()
val jsonAdapter: JsonAdapter<BlackjackHand> = moshi.adapter<BlackjackHand>()
val blackjackHand = jsonAdapter.fromJson(json)
println(blackjackHand) And it can just as easily serialize Java or Kotlin objects as JSON: JavaBlackjackHand blackjackHand = new BlackjackHand(
new Card('6', SPADES),
Arrays.asList(new Card('4', CLUBS), new Card('A', HEARTS)));
Moshi moshi = new Moshi.Builder().build();
JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class);
String json = jsonAdapter.toJson(blackjackHand);
System.out.println(json); Kotlinval blackjackHand = BlackjackHand(
Card('6', SPADES),
listOf(Card('4', CLUBS), Card('A', HEARTS))
)
val moshi: Moshi = Moshi.Builder().build()
val jsonAdapter: JsonAdapter<BlackjackHand> = moshi.adapter<BlackjackHand>()
val json: String = jsonAdapter.toJson(blackjackHand)
println(json) Built-in Type AdaptersMoshi has built-in support for reading and writing Java’s core data types:
It supports your model classes by writing them out field-by-field. In the example above Moshi uses these classes: Javaclass BlackjackHand {
public final Card hidden_card;
public final List<Card> visible_cards;
...
}
class Card {
public final char rank;
public final Suit suit;
...
}
enum Suit {
CLUBS, DIAMONDS, HEARTS, SPADES;
} Kotlinclass BlackjackHand(
val hidden_card: Card,
val visible_cards: List<Card>,
...
)
class Card(
val rank: Char,
val suit: Suit
...
)
enum class Suit {
CLUBS, DIAMONDS, HEARTS, SPADES;
} to read and write this JSON: {
"hidden_card": {
"rank": "6",
"suit": "SPADES"
},
"visible_cards": [
{
"rank": "4",
"suit": "CLUBS"
},
{
"rank": "A",
"suit": "HEARTS"
}
]
} The Javadoc catalogs the complete Moshi API, which we explore below. Custom Type AdaptersWith Moshi, it’s particularly easy to customize how values are converted to and from JSON. A type
adapter is any class that has methods annotated For example, Moshi’s default encoding of a playing card is verbose: the JSON defines the rank and
suit in separate fields: Javaclass CardAdapter {
@ToJson String toJson(Card card) {
return card.rank + card.suit.name().substring(0, 1);
}
@FromJson Card fromJson(String card) {
if (card.length() != 2) throw new JsonDataException("Unknown card: " + card);
char rank = card.charAt(0);
switch (card.charAt(1)) {
case 'C': return new Card(rank, Suit.CLUBS);
case 'D': return new Card(rank, Suit.DIAMONDS);
case 'H': return new Card(rank, Suit.HEARTS);
case 'S': return new Card(rank, Suit.SPADES);
default: throw new JsonDataException("unknown suit: " + card);
}
}
} Kotlinclass CardAdapter {
@ToJson fun toJson(card: Card): String {
return card.rank + card.suit.name.substring(0, 1)
}
@FromJson fun fromJson(card: String): Card {
if (card.length != 2) throw JsonDataException("Unknown card: $card")
val rank = card[0]
return when (card[1]) {
'C' -> Card(rank, Suit.CLUBS)
'D' -> Card(rank, Suit.DIAMONDS)
'H' -> Card(rank, Suit.HEARTS)
'S' -> Card(rank, Suit.SPADES)
else -> throw JsonDataException("unknown suit: $card")
}
}
} Register the type adapter with the JavaMoshi moshi = new Moshi.Builder()
.add(new CardAdapter())
.build(); Kotlinval moshi = Moshi.Builder()
.add(CardAdapter())
.build() Voilà: {
"hidden_card": "6S",
"visible_cards": [
"4C",
"AH"
]
} Another exampleNote that the method annotated with 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. {
"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. Also, we would like to have all variable names in CamelCase. Therefore, the Javaclass Event {
String title;
String beginDateAndTime;
} Kotlinclass Event(
val title: String,
val beginDateAndTime: String
) Instead of manually parsing the JSON line per line (which we could also do) we can have Moshi do the
transformation automatically. We simply define another class Javaclass EventJson {
String title;
String begin_date;
String begin_time;
} Kotlinclass EventJson(
val title: String,
val begin_date: String,
val begin_time: String
) And another class with the appropriate Javaclass 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;
}
} Kotlinclass EventJsonAdapter {
@FromJson
fun eventFromJson(eventJson: EventJson): Event {
return Event(
title = eventJson.title,
beginDateAndTime = "${eventJson.begin_date} ${eventJson.begin_time}"
)
}
@ToJson
fun eventToJson(event: Event): EventJson {
return EventJson(
title = event.title,
begin_date = event.beginDateAndTime.substring(0, 8),
begin_time = event.beginDateAndTime.substring(9, 14),
)
}
} Again we register the adapter with Moshi. JavaMoshi moshi = new Moshi.Builder()
.add(new EventJsonAdapter())
.build(); Kotlinval moshi = Moshi.Builder()
.add(EventJsonAdapter())
.build() We can now use Moshi to parse the JSON directly to an JavaJsonAdapter<Event> jsonAdapter = moshi.adapter(Event.class);
Event event = jsonAdapter.fromJson(json); Kotlinval jsonAdapter = moshi.adapter<Event>()
val event = jsonAdapter.fromJson(json) Adapter convenience methodsMoshi provides a number of convenience methods for
These factory methods wrap an existing JavaString dateJson = "\"2018-11-26T11:04:19.342668Z\"";
String nullDateJson = "null";
// Hypothetical IsoDateDapter, doesn't support null by default
JsonAdapter<Date> adapter = new IsoDateDapter();
Date date = adapter.fromJson(dateJson);
System.out.println(date); // Mon Nov 26 12:04:19 CET 2018
Date nullDate = adapter.fromJson(nullDateJson);
// Exception, com.squareup.moshi.JsonDataException: Expected a string but was NULL at path $
Date nullDate = adapter.nullSafe().fromJson(nullDateJson);
System.out.println(nullDate); // null Kotlinval dateJson = "\"2018-11-26T11:04:19.342668Z\""
val nullDateJson = "null"
// Hypothetical IsoDateDapter, doesn't support null by default
val adapter: JsonAdapter<Date> = IsoDateDapter()
val date = adapter.fromJson(dateJson)
println(date) // Mon Nov 26 12:04:19 CET 2018
val nullDate = adapter.fromJson(nullDateJson)
// Exception, com.squareup.moshi.JsonDataException: Expected a string but was NULL at path $
val nullDate = adapter.nullSafe().fromJson(nullDateJson)
println(nullDate) // null In contrast to Parse JSON ArraysSay we have a JSON string of this structure: [
{
"rank": "4",
"suit": "CLUBS"
},
{
"rank": "A",
"suit": "HEARTS"
}
] We can now use Moshi to parse the JSON string into a JavaString cardsJsonResponse = ...;
Type type = Types.newParameterizedType(List.class, Card.class);
JsonAdapter<List<Card>> adapter = moshi.adapter(type);
List<Card> cards = adapter.fromJson(cardsJsonResponse); Kotlinval cardsJsonResponse: String = ...
// We can just use a reified extension!
val adapter = moshi.adapter<List<Card>>()
val cards: List<Card> = adapter.fromJson(cardsJsonResponse) Fails GracefullyAutomatic databinding almost feels like magic. But unlike the black magic that typically accompanies reflection, Moshi is designed to help you out when things go wrong.
Moshi always throws a standard Built on OkioMoshi uses Okio for simple and powerful I/O. It’s a fine complement to OkHttp, which can share buffer segments for maximum efficiency. Borrows from GsonMoshi uses the same streaming and binding mechanisms as Gson. If you’re a Gson user you’ll find Moshi works similarly. If you try Moshi and don’t love it, you can even migrate to Gson without much violence! But the two libraries have a few important differences:
Custom field names with @JsonMoshi works best when your JSON objects and Java or Kotlin classes have the same structure. But when they don't, Moshi has annotations to customize data binding. Use {
"username": "jesse",
"lucky number": 32
} With Javaclass Player {
String username;
@Json(name = "lucky number") int luckyNumber;
...
} Kotlinclass Player {
val username: String
@Json(name = "lucky number") val luckyNumber: Int
...
} Because JSON field names are always defined with their Java or Kotlin fields, Moshi makes it easy to find fields when navigating between Java or Koltin and JSON. Alternate type adapters with @JsonQualifierUse Here’s a JSON message with two integers and a color: {
"width": 1024,
"height": 768,
"color": "#ff0000"
} By convention, Android programs also use Javaclass Rectangle {
int width;
int height;
int color;
} Kotlinclass Rectangle(
val width: Int,
val height: Int,
val color: Int
) But if we encoded the above Java or Kotlin class as JSON, the color isn't encoded properly! {
"width": 1024,
"height": 768,
"color": 16711680
} The fix is to define a qualifier annotation, itself annotated Java@Retention(RUNTIME)
@JsonQualifier
public @interface HexColor {
} Kotlin@Retention(RUNTIME)
@JsonQualifier
annotation class HexColor Next apply this Javaclass Rectangle {
int width;
int height;
@HexColor int color;
} Kotlinclass Rectangle(
val width: Int,
val height: Int,
@HexColor val color: Int
) And finally define a type adapter to handle it: Java/** Converts strings like #ff0000 to the corresponding color ints. */
class ColorAdapter {
@ToJson String toJson(@HexColor int rgb) {
return String.format("#%06x", rgb);
}
@FromJson @HexColor int fromJson(String rgb) {
return Integer.parseInt(rgb.substring(1), 16);
}
} Kotlin/** Converts strings like #ff0000 to the corresponding color ints. */
class ColorAdapter {
@ToJson fun toJson(@HexColor rgb: Int): String {
return "#%06x".format(rgb)
}
@FromJson @HexColor fun fromJson(rgb: String): Int {
return rgb.substring(1).toInt(16)
}
} Use Omitting fieldsSome models declare fields that shouldn’t be included in JSON. For example, suppose our blackjack
hand has a Javapublic final class BlackjackHand {
private int total;
...
} Kotlinclass BlackjackHand(
private val total: Int,
...
) By default, all fields are emitted when encoding JSON, and all fields are accepted when decoding
JSON. Prevent a field from being included by annotating them with Java全部评论
专题导读
上一篇:dsznajder/vscode-react-javascript-snippets: Extension for React/Javascript snipp ...发布时间:2022-06-23下一篇:PacktPublishing/Java-Coding-Problems: Java Coding Problems, published by Packt发布时间:2022-06-23热门推荐
热门话题
阅读排行榜
|
请发表评论