JSON är det textformat som har blivit väldigt populärt eftersom det är lätt att skriva och läsa för både människor och maskiner. XML var länge standardsättet att kommunicera med webbtjänster, men med JavaScripts intåg och dess inbyggda stöd för att konvertera mellan textformat och objekt har JSON blivit det absolut vanligaste formatet.

När vi läser eller skriver JSON är det i grund och botten strängar som hanteras. Som utvecklare av webbtjänster i Java behöver vi tolka förfrågningar och skicka svar. Data är ofta hårt typad och lagrad i POJOs (Plain Old Java Objects). Det är en standarduppgift: inget som ska ta för mycket tid att bygga, men som ändå måste fungera pålitligt och stabilt.

Jackson är ett trevligt bibliotek som kan hjälpa oss att lösa utmaningarna med att hantera JSON i Java. Med bara några rader kod kan vi omvandla ett objekt till en sträng redo att skickas över nätverket, eller läsa in en JSON-ström från en fil och omvandla den till ett objekt. Om du har arbetat med Spring Boot tidigare har du troligen redan stött på Jackson, eftersom det är standardbiblioteket för JSON-hantering där.

För att komma igång och arbeta med biblioteket behöver rätt beroenden läggas till Maven i pom.xml. Det går att hitta senaste på MVN Repository. I dag finns det huvudsakligen två versioner 1.x som inte aktivt utvecklas längre och version 2.x som är aktiv version. 3.x är under utveckling och kommer att släppas som ett eget paket (hösten 2025). När du bestämt vilken version du vill använda kan du kopiera rätt beroenden och lägga till dessa till pom.xml.

Kom igång

För att börja arbeta med biblioteket behöver rätt beroenden läggas till i pom.xml. Du hittar de senaste versionerna på MVN Repository.

I dag finns huvudsakligen två versioner:

  • 1.x – inte längre aktivt utvecklad
  • 2.x – den aktuella, aktivt utvecklade versionen
  • 3.x – under utveckling, planeras släppas som eget paket (hösten 2025)

När du har bestämt vilken version du vill använda kan du kopiera beroenderaden och lägga till den i pom.xml:

<!--
https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind 
-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.20.0</version>
</dependency>

Exempel: konvertera mellan objekt och JSON

Med hjälp av Jacksons databindings går det enkelt att konvertera mellan JSON och POJOs.

// Vi använder här en record istället för en klass
public record SuperHero(String name, int hp) {  };

public static void testJackson() throws JsonProcessingException {  
    // Skapa en instans av ObjectMapper
    ObjectMapper mapper = new ObjectMapper();  

    // Skapa en superhjälte med data
    SuperHero superMan = new SuperHero(
        "Superman", 
        2000
    );  

    // Konvertera objektet till en JSON-sträng
    String superManAsJson = mapper.writeValueAsString(superMan); 

    // Skriv ut resultatet på skärmen
    System.out.println(superManAsJson);  


    // Skapa en sträng med JSON
    String superHeroJson = "{ \"name\" : \"Cat Woman\", " +
        "\"hp\" : 2002 }";

    // Konvertera stränget till ett objekt
    SuperHero catWoman = mapper.readValue(
        superHeroJson, 
        SuperHero.class
    );  

    // Skriv ut resultatet på skärmen
    System.out.println(catWoman);
}

JSON som trädstruktur

Ibland har man JSON som behöver läsas in, men det finns ingen motsvarande klass. Då kan man istället läsa in datan som en trädstruktur.

// Konvertera JSON från sträng till nodes
JsonNode jsonNode = mapper.readTree(superHeroJson);  

// Hämta ut värdena med hjälp av getters
String name = jsonNode.get("name").asText();  
int hp = jsonNode.get("hp").asInt();  

// Skriv ut resultatet på skärmen
System.out.println(
    "SuperHero was: name = " + name + 
    " hp = " + hp
);

Hantering av filer

Om datan finns i filer går det bra att använda readValue och writeValue direkt mot en fil.

// Skriv objektet som en JSON-fil
mapper.writeValue(new File("out.json"), superMan);

// Läs in en fil till ett nytt objekt
SuperHero superManFromFile = mapper.readValue(
    new File("out.json"), 
    SuperHero.class
);

Utöver detta går det även enkelt att arbeta med strömmar och byte-arrayer. Detta gör Jackson till ett smidigt och kraftfullt bibliotek.

Anpassning med annoteringar

En annan styrka med Jackson är flexibiliteten i hur konverteringen fungerar – både från objekt till JSON och från JSON till objekt.

Tänk dig att du har ett förbestämt JSON-format som inte matchar med namngivningen i din klass. Med Java-annoteringar kan detta anpassas.

Vi har en klass för skurkar, med name och damage. Dessutom kan skurkar ha hantlangare representerade av en Map<String, Villain>.

public class Villain {  

    private String name;  
    private int damage;  
    private Map<String, Villain> henchmen = new HashMap<>();

    // Setters och Getters här    
}

Men i vårt JSON-format heter damage istället strength. Dessutom representeras hantlangare som egna attribut. Exempel:

{
    "name":"Bob",
    "strength":33,
    "Accountant": {
        "name":"Henry",
        "strength":8
    },
    "Doorman": {
        "name":"Burt",
        "strength":12
    }
}

Vi kan lösa detta enkelt genom att arbeta med Jackson annoteringar. Med hjälp av @JsonGetteroch @JsonSetterkan vi styra hur klassen konverteras till och från JSON:

@JsonGetter("strength")  
public int getDamage() {  
    return damage;  
}  

@JsonSetter("strength")  
public void setDamage(int damage) {  
    this.damage = damage;  
}

Damage kommer nu att heta strength både när JSON skapas eller omvandlas till objekt. Detta var enkelt. Nästa steg är att vi behöver hantera vår dörrvakt. Här kan vi använda @JsonAnySetteroch @JsonAnyGetter.

@JsonAnyGetter  
public Map<String, Villain> getHenchmen() {  
    return henchmen;  
}

// Notera att sätter tar emot nyckel/värde - inte hela
// map:en. 
@JsonAnySetter  
public void setHenchmen(String key, Villain villain){  
    this.henchmen.put(key, villain);  
}

På detta sätt kan vi styra exakt hur konverteringen ska gå till. Jacksons ObjectMapper används som tidigare för att konvertera till och från JSON. Du kan hitta hela Villain.java här.