[JAVA] Entspricht einer Eigenschaft, deren Typ mit JsonDeserializer leer wird, wenn er leer ist

Überblick

Es gibt eine API, die JSON mit Eigenschaften des Objekttyps zurückgibt, wenn ein Wert vorhanden ist, und einen Array-Typ, wenn dieser leer ist. Standardmäßig stimmen die Typen nicht überein und können nicht an die Klasse gebunden werden.

Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `net.yotama.sample.resource.Resource$Member` out of START_ARRAY token
 at [Source: (String)"{"member": []}"; line: 1, column: 12](through reference chain: net.yotama.sample.resource.Resource["member"])

Verwenden Sie Jacksons JsonDeserializer und ersetzen Sie ihn durch null, wenn es sich um ein Array handelt, damit es an eine Ressourcenklasse gebunden werden kann.

Angenommene JSON-Antwort

Wenn es einen Wert gibt

{
    "member": {
        "name": "yotama"
    }
}

Wenn es keinen Wert gibt

{
    "member": []
}

Umgebung

Implementierung

Ressourcenklasse

Resource.java


package net.yotama.sample.resource;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Value;

import java.io.IOException;

@Value
public class Resource {
    @JsonDeserialize(using = MemberDeserializer.class)
    Member member;

    @Value
    public static class Member {
        String name;
    }

    public static class MemberDeserializer extends JsonDeserializer<Member> {
        private ObjectMapper objectMapper = new ObjectMapper();

        @Override
        public Member deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            TreeNode treeNode = p.getCodec().readTree(p);
            return treeNode.isObject() ? objectMapper.readValue(treeNode.toString(), Member.class) : null;
        }
    }
}

lombok.config


#Ich benutze Lombok der Einfachheit halber,
# 1.16.Verwendet von Jackson ab 20@ConstructorProperties werden nicht zugewiesen. Legen Sie sie daher vorläufig fest
lombok.anyConstructor.addConstructorProperties=true

Funktionsprüfung

package net.yotama.sample.resource;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;

import java.io.IOException;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

@RunWith(Theories.class)
public class ResourceTest {
    private ObjectMapper objectMapper = new ObjectMapper();

    @DataPoints
    public static Fixture[] data = {
            new Fixture("{\"member\": []}", new Resource(null)),
            new Fixture("{\"member\": null}", new Resource(null)),
            new Fixture("{\"member\": {\"name\": \"hoge\"}}", new Resource(new Resource.Member("hoge"))),
    };

    @Theory
    public void test(Fixture fixture) throws IOException {
        assertThat(objectMapper.readValue(fixture.json, Resource.class), is(fixture.expected));
    }

    @RequiredArgsConstructor
    public static class Fixture {
        final String json;
        final Resource expected;
    }
}

Recommended Posts

Entspricht einer Eigenschaft, deren Typ mit JsonDeserializer leer wird, wenn er leer ist
Beim Zuweisen zu einem Array wird ein Nullwert eingegeben
So geben Sie den Wert aus, wenn sich ein Array im Array befindet
Duplizieren Sie ein Objekt mit einem generischen Typ
Rufen Sie den Typ eines Elements eines Arrays ab, um festzustellen, ob es sich um ein Array handelt
[Java] So konvertieren Sie ein Element eines Array vom Typ String in einen Int-Typ
Ich möchte eine Verbindung herstellen, wenn eine Datenbank mit Spring und MyBatis erstellt wird
So verwenden Sie ein Array für den TreeMap-Schlüssel
Ein Memorandum beim Versuch, eine GUI mit JavaFX zu erstellen
[Nicht gelöst] Eine Ausnahme tritt auf, wenn eine SSH-Verbindung mit JSch aus einer Java 6-App ausgeführt wird.
Ein Fehler beim Anzeigen eines Bildes mit Active Storage
So ändern Sie eine Zeichenfolge in einem Array in eine Zahl in Ruby
Initialisierung mit einer leeren Zeichenfolge für eine Instanz vom Typ Java-Zeichenfolge
So geben Sie Array-Werte ohne Verwendung einer for-Anweisung aus
Konvertieren Sie ein potenziell null-Array in einen Stream
Affen-Patch, um die aktuelle Zeit zurückzugeben, wenn in Time.parse of Ruby eine leere Zeichenfolge angegeben ist