2

I'm trying to read this json file:

{
  "username": "someusername",
  "password": "12345678",
  "ipAddresses": {
    "2015-09-12": "127.0.0.1"
  }
}

Using this class to store the info:

private final class SavedPlayer {
    private final String username;
    private final String password;
    private final HashMap<LocalDate, String> ipAddresses;

    private SavedPlayer(
            String username, String password,
            HashMap<LocalDate, String> ipAddresses
    ) {
        this.username = username;
        this.password = password;
        this.ipAddresses = ipAddresses;
    }
}

And this part of the code throws an exception:

private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
SavedPlayer savedPlayer = GSON.fromJson(reader, SavedPlayer.class);

This is the thrown exception:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 5 column 17

How can I read this stored HashMap properly?

Edit: it works fine when i use <String, String> instead of <LocalDate, String>

user2997204
  • 1,344
  • 2
  • 12
  • 24

3 Answers3

1

To bind JSON to LocalDate, you either have to write your custom serializer/deserialzer by implementing JsonDeserializer and registering with GSON using method registerTypeAdapter(), or you can use existing library for that: https://github.com/gkopff/gson-javatime-serialisers

Kejml
  • 2,114
  • 1
  • 21
  • 31
1

Gson allows you to register your own custom serializers and deserializers. This is done by defining two parts:

Json Serialiers: Need to define custom serialization for an object Json Deserializers: Needed to define custom deserialization for a type Instance Creators: Not needed if no-args constructor is available or a deserializer is registered

GsonBuilder gson = new GsonBuilder();
gson.registerTypeAdapter(LocalDate.class, new MyDeserializer());

registerTypeAdapter call checks if the type adapter implements more than one of these interfaces and register it for all of them.

for more information check gson-user-guide

Here is an example of how to write a custom deserialize for LocalDate

public class LocalDateJsonDeserializer implements JsonDeserializer<LocalDate> {    
      public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
          throws JsonParseException {
        return new LocalDate(json.getAsJsonPrimitive().getAsString());
      }
}

and use this line for creating GSON.

final static Gson GSON = new GsonBuilder().registerTypeAdapter(LocalDate.class, new LocalDateJsonDeserializer()).setPrettyPrinting().create();
0

Edit: You can find GSON deserializing key-value to custom object.


I tried the code you pasted with Gson 2.4 library. Also I converted the LocalDate to String. It is working absolutely fine.

public class SavedPlayer {
  private final String username;
  private final String password;
  private final HashMap<String, String> ipAddresses;

  private SavedPlayer(
      String username, String password,
      HashMap<String, String> ipAddresses
  ) {
    this.username = username;
    this.password = password;
    this.ipAddresses = ipAddresses;
  }

  public static void main(String[] args) throws FileNotFoundException {
    final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
    SavedPlayer savedPlayer = GSON.fromJson("{\n" +
        "  \"username\": \"someusername\",\n" +
        "  \"password\": \"12345678\",\n" +
        "  \"ipAddresses\": {\n" +
        "    \"2015-09-12\": \"127.0.0.1\"\n" +
        "  }\n" +
        "}", SavedPlayer.class);
    System.out.println(savedPlayer.username);
    System.out.println(savedPlayer.password);
    for (Map.Entry entry : savedPlayer.ipAddresses.entrySet()) {
      System.out.println("Key: " + entry.getKey() + "\tValue: " + entry.getValue());
    }
  }
}

Output:
someusername
12345678
Key: 2015-09-12 Value: 127.0.0.1

Community
  • 1
  • 1
YoungHobbit
  • 13,254
  • 9
  • 50
  • 73