Как десериализовать строку JSON в непубличный класс, используя JSON-B?
Я создал три приложения Java 9 Maven с двумя классами для тестирования сериализации и десериализации JSON с использованием JSON-B. Вот код:
package com.jsonbdemos;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbConfig;
public class App {
public static void main(String[] args) {
Jsonb jsonb = JsonbBuilder.create(new JsonbConfig());
String jsonData = "{\"creationDate\":\"2018-01-05\"}";
// Create Widget object from JSON string.
Widget widget = jsonb.fromJson(jsonData, Widget.class);
System.out.println("JSON => object: " + widget.toString());
// Serialize Widget object to JSON string.
String jsonFromObject = jsonb.toJson(widget);
System.out.println("object => JSON: " + jsonFromObject);
}
}
package com.jsonbdemos;
import java.time.LocalDate;
public class Widget { // IllegalAccessException if "public" is removed.
private LocalDate creationDate;
public Widget() {}
@Override
public String toString() { return "creationDate=" + creationDate; }
public LocalDate getCreationDate() { return creationDate; }
public void setCreationDate(LocalDate creationDate) { this.creationDate = creationDate; }
}
Существует зависимость для последней версии эталонной реализации JSON-B ( Eclipse Yasson) в pom.xml:
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>[1.1.2,)</version>
</dependency>
<dependency>
<groupId>javax.json.bind</groupId>
<artifactId>javax.json.bind-api</artifactId>
<version>[1.0,)</version>
</dependency>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>yasson</artifactId>
<version>[1.0.0,)</version>
</dependency>
Приложение работает нормально, но если я изменю уровень доступа класса Widget с общедоступного на ничто (т. Е. "Пакет приватный"), при вызове Jsonb.fromJson() выдается исключение IllegalAccessException:
Исключение в потоке "main" javax.json.bind.JsonbException: не удается создать экземпляр в org.eclipse.yasson.internal.ReflectionUtils.lambda$createNoArgConstructorInstance$1(ReflectionUtils.java:191) в java.base/java.security.AccessController. eclipse.yasson.internal.serializer. Unmarshaller.java:50) в org.eclipse.yasson.internal.JsonBinding.deserialize(JsonBinding.java:45) в org.eclipse.yasson.internal.JsonBinding.fromJson(JsonBinding.java:52) в com.jsonbdemos.App.main(App.java:15) Причина : java.lang.IllegalAccessException: класс org.ec lipse.yasson.internal.ReflectionUtils не может получить доступ к члену класса com.jsonbdemos.Widget с модификаторами public в java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361) в java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:589) в java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:479) в org.eclipse.yasson.internal.ReflectionUtils.lambg $1(ReflectionUtils.java:189) ... еще 9
Я не вижу в спецификации ничего ( JSR 367: "JSON-B: API Java ™ для привязки JSON") (в разделе 3.7 Java Class), требующего открытый класс для десериализации.
Любые предложения о том, как десериализовать в экземпляр класса, который не является общедоступным с использованием JSON-B?
Обновление (5/2/18):
В JSR 367 говорится, что " любой экземпляр, переданный операции десериализации, должен иметь открытый или защищенный конструктор без аргументов ", но такая же ошибка также возникает, если конструктор является защищенным, а не общедоступным.
Я сообщил об этой проблеме: десериализация все еще не работает с защищенным конструктором без аргументов #118
0 ответов
Я проверил несколько вариантов этого со следующими результатами:
Автономный класс (собственный исходный файл):
- класс = общедоступный, ctor = общедоступный = УСПЕХ
- класс = общедоступный, ctor = защищенный = УСПЕХ
- класс = общедоступный, ctor=pkg-protected = НЕЗАКОННЫЙ ДОСТУП
- класс = pkg-защищенный, ctor = public = НЕЗАКОННЫЙ ДОСТУП
Статический внутренний класс:
- класс = общедоступный, ctor = общедоступный = УСПЕХ
- класс = защищенный, ctor = общедоступный = УСПЕХ
- класс = pkg-защищенный, ctor = public = НЕЗАКОННЫЙ ДОСТУП
- класс = общедоступный, ctor = защищенный = УСПЕХ
- класс = общедоступный, ctor=pkg-protected = НЕЗАКОННЫЙ ДОСТУП
Нестатический внутренний класс:
- class = public, ctor = public = НЕЗАКОННЫЙ ДОСТУП
Ключевые моменты из этого:
- Публичные и защищенные работы, но защищенные пакетами или менее не работают (и класс, и ctor должны иметь равную или более высокую видимость, чем защищенные).
- Статические внутренние классы ведут себя так же, как и автономные классы.
- Нестатические внутренние классы недоступны, потому что для их создания требуется экземпляр внешнего класса.