diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocationsPersistence.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocationsPersistence.java
new file mode 100644
index 0000000000000000000000000000000000000000..27798efbb53f54058b6172a293220c72bcf092d1
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/core/GeoLocationsPersistence.java
@@ -0,0 +1,10 @@
+package tdt4140.gr1800.app.core;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+
+public interface GeoLocationsPersistence {
+	public Collection<GeoLocations> loadLocations(InputStream inputStream) throws Exception;
+	public void saveLocations(Collection<GeoLocations> geoLocations, OutputStream outputStream) throws Exception;
+}
diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/json/GeoLocationsJsonDeserializer.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/json/GeoLocationsJsonDeserializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..c5f0e3dd4e844e3eb6803d31181fd24d746ba2dd
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/json/GeoLocationsJsonDeserializer.java
@@ -0,0 +1,69 @@
+package tdt4140.gr1800.app.json;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import tdt4140.gr1800.app.core.GeoLocations;
+import tdt4140.gr1800.app.core.LatLong;
+
+public class GeoLocationsJsonDeserializer extends StdDeserializer<GeoLocations> {
+	
+	public GeoLocationsJsonDeserializer() {
+		super(GeoLocations.class);
+	}
+	
+	@Override
+	public GeoLocations deserialize(JsonParser jsonParser, DeserializationContext deserContext) throws IOException, JsonProcessingException {
+		JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser);
+		return deserialize(jsonNode);
+	}
+	
+	private GeoLocations deserialize(JsonNode jsonNode) throws IOException, JsonProcessingException {
+		if (jsonNode instanceof ObjectNode) {
+			ObjectNode objectNode = (ObjectNode) jsonNode;
+			String name = objectNode.get(GeoLocationsJsonSerializer.NAME_FIELD_NAME).asText();
+			GeoLocations geoLocations = new GeoLocations(name);
+			JsonNode pathNode = objectNode.get(GeoLocationsJsonSerializer.PATH_FIELD_NAME);
+			geoLocations.setPath(pathNode != null && pathNode.asBoolean(false));
+			JsonNode locationsNode = objectNode.get(GeoLocationsJsonSerializer.LOCATIONS_FIELD_NAME);
+			if (locationsNode instanceof ArrayNode) {
+				for (JsonNode locationNode : (ArrayNode) locationsNode) {
+					LatLong latLong = decodeLatLong(locationNode);
+					geoLocations.addLocation(latLong);
+				}
+			} else {
+				LatLong latLong = decodeLatLong(locationsNode);
+				geoLocations.addLocation(latLong);				
+			}
+			return geoLocations;
+		}
+		return null;
+	}
+
+	private LatLong decodeLatLong(JsonNode locationNode) {
+		LatLong latLong = null;
+		if (locationNode instanceof ObjectNode) {
+			ObjectNode objectNode = (ObjectNode) locationNode;
+			if (objectNode.has(GeoLocationsJsonSerializer.LATITUDE_FIELD_NAME) && objectNode.has(GeoLocationsJsonSerializer.LONGITUDE_FIELD_NAME)) {
+				double lat = objectNode.get(GeoLocationsJsonSerializer.LATITUDE_FIELD_NAME).asDouble();
+				double lon = objectNode.get(GeoLocationsJsonSerializer.LONGITUDE_FIELD_NAME).asDouble();
+				latLong = new LatLong(lat, lon);
+			}
+		} else if (locationNode instanceof ArrayNode) {
+			ArrayNode arrayNode = (ArrayNode) locationNode;
+			if (arrayNode.size() == 2) {
+				double lat = arrayNode.get(0).asDouble();
+				double lon = arrayNode.get(1).asDouble();
+				latLong = new LatLong(lat, lon);			
+			}
+		}
+		return latLong;
+	}
+}
diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/json/GeoLocationsJsonPersistence.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/json/GeoLocationsJsonPersistence.java
new file mode 100644
index 0000000000000000000000000000000000000000..48804fb300bf362c0bfeffd57e24da07f328697a
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/json/GeoLocationsJsonPersistence.java
@@ -0,0 +1,35 @@
+package tdt4140.gr1800.app.json;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.List;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+import tdt4140.gr1800.app.core.GeoLocations;
+import tdt4140.gr1800.app.core.GeoLocationsPersistence;
+
+public class GeoLocationsJsonPersistence implements GeoLocationsPersistence {
+
+	private final ObjectMapper objectMapper;
+
+	public GeoLocationsJsonPersistence() {
+		objectMapper = new ObjectMapper();
+		SimpleModule module = new SimpleModule();
+		module.addSerializer(new GeoLocationsJsonSerializer());
+		module.addDeserializer(GeoLocations.class, new GeoLocationsJsonDeserializer());
+		objectMapper.registerModule(module);
+	}
+	
+	@Override
+	public Collection<GeoLocations> loadLocations(InputStream inputStream) throws Exception {
+		return objectMapper.readValue(inputStream, objectMapper.getTypeFactory().constructCollectionType(List.class, GeoLocations.class));
+	}
+
+	@Override
+	public void saveLocations(Collection<GeoLocations> geoLocations, OutputStream outputStream) throws Exception {
+		objectMapper.writeValue(outputStream, geoLocations);
+	}
+}
diff --git a/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/json/GeoLocationsJsonSerializer.java b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/json/GeoLocationsJsonSerializer.java
new file mode 100644
index 0000000000000000000000000000000000000000..da7aa070edbb165e2e29c7b87ffc7c57467a54aa
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/main/java/tdt4140/gr1800/app/json/GeoLocationsJsonSerializer.java
@@ -0,0 +1,42 @@
+package tdt4140.gr1800.app.json;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+import tdt4140.gr1800.app.core.GeoLocations;
+import tdt4140.gr1800.app.core.LatLong;
+
+public class GeoLocationsJsonSerializer extends StdSerializer<GeoLocations> {
+	
+	public static final String LONGITUDE_FIELD_NAME = "longitude";
+	public static final String LATITUDE_FIELD_NAME = "latitude";
+	public static final String LOCATIONS_FIELD_NAME = "locations";
+	public static final String PATH_FIELD_NAME = "path";
+	public static final String NAME_FIELD_NAME = "name";
+
+	public GeoLocationsJsonSerializer() {
+		super(GeoLocations.class);
+	}
+
+	@Override
+	public void serialize(GeoLocations geoLocations, JsonGenerator jsonGen, SerializerProvider serProvider) throws IOException {
+		jsonGen.writeStartObject();
+		jsonGen.writeFieldName(NAME_FIELD_NAME);
+		jsonGen.writeString(geoLocations.getName());
+		jsonGen.writeFieldName(PATH_FIELD_NAME);
+		jsonGen.writeBoolean(geoLocations.isPath());
+		jsonGen.writeFieldName(LOCATIONS_FIELD_NAME);
+		jsonGen.writeStartArray();
+		for (LatLong latLon : geoLocations) {
+			jsonGen.writeStartArray();
+			jsonGen.writeNumber(latLon.latitude);
+			jsonGen.writeNumber(latLon.longitude);
+			jsonGen.writeEndArray();
+		}
+		jsonGen.writeEndArray();
+		jsonGen.writeEndObject();
+	}
+}
diff --git a/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsPersistenceTest.java b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsPersistenceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..08f61251a6d88c8e0582a93f9c9e3e5aa82dc5ed
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/test/java/tdt4140/gr1800/app/core/GeoLocationsPersistenceTest.java
@@ -0,0 +1,56 @@
+package tdt4140.gr1800.app.core;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import tdt4140.gr1800.app.json.GeoLocationsJsonPersistence;
+
+public class GeoLocationsPersistenceTest {
+
+	private GeoLocationsPersistence persistence;
+	
+	@Before
+	public void setUp() {
+		persistence = new GeoLocationsJsonPersistence();
+	}
+	
+	@Test
+	public void testLoadLocations() {
+		testLoadLocations(getClass().getResourceAsStream("geoLocations.json"));
+	}
+	
+	private void testLoadLocations(InputStream inputStream) {
+		try {
+			Collection<GeoLocations> geoLocations = persistence.loadLocations(inputStream);
+			Assert.assertEquals(2, geoLocations.size());
+			Iterator<GeoLocations> it = geoLocations.iterator();
+			GeoLocationsTest.assertGeoLocations(it.next(), new LatLong(63, 10), new LatLong(63.1, 10.1));
+			GeoLocationsTest.assertGeoLocations(it.next(), new LatLong(64, 11), new LatLong(64.1, 11.1));
+		} catch (Exception e) {
+			Assert.fail(e.getMessage());
+		}
+	}
+
+	@Test
+	public void testSaveLocations() {
+		Collection<GeoLocations> geoLocations = new ArrayList<GeoLocations>();
+		geoLocations.add(new GeoLocations("1", new LatLong(63, 10), new LatLong(63.1, 10.1)));
+		geoLocations.add(new GeoLocations("2", new LatLong(64, 11), new LatLong(64.1, 11.1)));
+		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+		try {
+			persistence.saveLocations(geoLocations, outputStream);
+			outputStream.close();
+			testLoadLocations(new ByteArrayInputStream(outputStream.toByteArray()));
+		} catch (Exception e) {
+			Assert.fail(e.getMessage());
+		}
+	}
+}
diff --git a/tdt4140-gr1800/app.core/src/test/resources/tdt4140/gr1800/app/core/geoLocations.json b/tdt4140-gr1800/app.core/src/test/resources/tdt4140/gr1800/app/core/geoLocations.json
new file mode 100644
index 0000000000000000000000000000000000000000..bfda7a4524d5419067f9a0dba069740402aff30d
--- /dev/null
+++ b/tdt4140-gr1800/app.core/src/test/resources/tdt4140/gr1800/app/core/geoLocations.json
@@ -0,0 +1,17 @@
+[
+  {
+    "name" : "1",
+    "locations" : [
+      { "latitude" : "63", "longitude" : "10" },
+      [ "63.1", "10.1" ]
+    ]
+  },
+  {
+    "name" : "2",
+    "path" : "true",
+    "locations" : [
+      { "latitude" : "64", "longitude" : "11" },
+      [ "64.1", "11.1" ]
+    ]
+  }
+]