Flutter Engine
The Flutter Engine
JSONMethodCodec.java
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package io.flutter.plugin.common;
6
7import androidx.annotation.NonNull;
8import androidx.annotation.Nullable;
9import java.nio.ByteBuffer;
10import org.json.JSONArray;
11import org.json.JSONException;
12import org.json.JSONObject;
13
14/**
15 * A {@link MethodCodec} using UTF-8 encoded JSON method calls and result envelopes.
16 *
17 * <p>This codec is guaranteed to be compatible with the corresponding <a
18 * href="https://api.flutter.dev/flutter/services/JSONMethodCodec-class.html">JSONMethodCodec</a> on
19 * the Dart side. These parts of the Flutter SDK are evolved synchronously.
20 *
21 * <p>Values supported as methods arguments and result payloads are those supported by {@link
22 * JSONMessageCodec}.
23 */
24public final class JSONMethodCodec implements MethodCodec {
25 // This codec must match the Dart codec of the same name in package flutter/services.
26 public static final JSONMethodCodec INSTANCE = new JSONMethodCodec();
27
28 private JSONMethodCodec() {}
29
30 @Override
31 @NonNull
32 public ByteBuffer encodeMethodCall(@NonNull MethodCall methodCall) {
33 try {
34 final JSONObject map = new JSONObject();
35 map.put("method", methodCall.method);
36 map.put("args", JSONUtil.wrap(methodCall.arguments));
38 } catch (JSONException e) {
39 throw new IllegalArgumentException("Invalid JSON", e);
40 }
41 }
42
43 @Override
44 @NonNull
45 public MethodCall decodeMethodCall(@NonNull ByteBuffer message) {
46 try {
48 if (json instanceof JSONObject) {
49 final JSONObject map = (JSONObject) json;
50 final Object method = map.get("method");
51 final Object arguments = unwrapNull(map.opt("args"));
52 if (method instanceof String) {
53 return new MethodCall((String) method, arguments);
54 }
55 }
56 throw new IllegalArgumentException("Invalid method call: " + json);
57 } catch (JSONException e) {
58 throw new IllegalArgumentException("Invalid JSON", e);
59 }
60 }
61
62 @Override
63 @NonNull
64 public ByteBuffer encodeSuccessEnvelope(@Nullable Object result) {
65 return JSONMessageCodec.INSTANCE.encodeMessage(new JSONArray().put(JSONUtil.wrap(result)));
66 }
67
68 @Override
69 @NonNull
70 public ByteBuffer encodeErrorEnvelope(
71 @NonNull String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) {
73 new JSONArray()
74 .put(errorCode)
75 .put(JSONUtil.wrap(errorMessage))
76 .put(JSONUtil.wrap(errorDetails)));
77 }
78
79 @Override
80 @NonNull
82 @NonNull String errorCode,
83 @Nullable String errorMessage,
84 @Nullable Object errorDetails,
85 @Nullable String errorStacktrace) {
87 new JSONArray()
88 .put(errorCode)
89 .put(JSONUtil.wrap(errorMessage))
90 .put(JSONUtil.wrap(errorDetails))
91 .put(JSONUtil.wrap(errorStacktrace)));
92 }
93
94 @Override
95 @NonNull
96 public Object decodeEnvelope(@NonNull ByteBuffer envelope) {
97 try {
98 final Object json = JSONMessageCodec.INSTANCE.decodeMessage(envelope);
99 if (json instanceof JSONArray) {
100 final JSONArray array = (JSONArray) json;
101 if (array.length() == 1) {
102 return unwrapNull(array.opt(0));
103 }
104 if (array.length() == 3) {
105 final Object code = array.get(0);
106 final Object message = unwrapNull(array.opt(1));
107 final Object details = unwrapNull(array.opt(2));
108 if (code instanceof String && (message == null || message instanceof String)) {
109 throw new FlutterException((String) code, (String) message, details);
110 }
111 }
112 }
113 throw new IllegalArgumentException("Invalid envelope: " + json);
114 } catch (JSONException e) {
115 throw new IllegalArgumentException("Invalid JSON", e);
116 }
117 }
118
119 Object unwrapNull(Object value) {
120 return (value == JSONObject.NULL) ? null : value;
121 }
122}
Object decodeMessage(@Nullable ByteBuffer message)
static final JSONMessageCodec INSTANCE
ByteBuffer encodeMessage(@Nullable Object message)
ByteBuffer encodeSuccessEnvelope(@Nullable Object result)
MethodCall decodeMethodCall(@NonNull ByteBuffer message)
ByteBuffer encodeErrorEnvelopeWithStacktrace( @NonNull String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails, @Nullable String errorStacktrace)
static final JSONMethodCodec INSTANCE
Object decodeEnvelope(@NonNull ByteBuffer envelope)
ByteBuffer encodeErrorEnvelope( @NonNull String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails)
ByteBuffer encodeMethodCall(@NonNull MethodCall methodCall)
static Object wrap(@Nullable Object o)
Definition: JSONUtil.java:63
static ::testing::Matcher< GBytes * > MethodCall(const std::string &name, ::testing::Matcher< FlValue * > args)
uint8_t value
GAsyncResult * result
Win32Message message
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
Definition: SkVx.h:680