diff --git a/src/main/java/com/comandante/creeper/ConfigureNpc.java b/src/main/java/com/comandante/creeper/ConfigureNpc.java
index 4d7161e4824f206ab0dbdc07256bb5d93963facd..03476fc3ad7a2881e86b940b738c3204b7d3f95d 100644
--- a/src/main/java/com/comandante/creeper/ConfigureNpc.java
+++ b/src/main/java/com/comandante/creeper/ConfigureNpc.java
@@ -20,116 +20,34 @@ import com.comandante.creeper.world.Area;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 
+import java.io.FileNotFoundException;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 public class ConfigureNpc {
 
-    public static void configure(EntityManager entityManager, GameManager gameManager) {
-        Main.startUpMessage("Adding Street Hustlers");
-        entityManager.addEntity(new NpcSpawner(new StreetHustler(gameManager, new Loot(1, 3, Sets.<Item>newHashSet())), Sets.newHashSet(Area.NEWBIE_ZONE), gameManager, new SpawnRule(10, 5, 3, 100)));
+    public static void configure(EntityManager entityManager, GameManager gameManager) throws FileNotFoundException {
+
+        List<Npc> npcsFromFile = NpcExporter.getNpcsFromFile(gameManager);
+        for (Npc npc: npcsFromFile) {
+            System.out.println("added streethustlers");
+            entityManager.addEntity(npc);
+            Set<SpawnRule> spawnRules = npc.getSpawnRules();
+            for (SpawnRule spawnRule: spawnRules) {
+                entityManager.addEntity(new NpcSpawner(npc, gameManager, spawnRule));
+            }
+        }
 
         Main.startUpMessage("Adding beer");
-        ItemSpawner itemSpawner = new ItemSpawner(ItemType.BEER, Area.NEWBIE_ZONE, new SpawnRule(10, 100, 5, 40), gameManager);
-        ItemSpawner itemSpawner1 = new ItemSpawner(ItemType.BEER, Area.FANCYHOUSE_ZONE, new SpawnRule(10, 12, 2, 50), gameManager);
-        ItemSpawner itemSpawner2 = new ItemSpawner(ItemType.BEER, Area.HOUSE_ZONE, new SpawnRule(10, 12, 2, 50), gameManager);
+        ItemSpawner itemSpawner = new ItemSpawner(ItemType.BEER, new SpawnRule(Area.NEWBIE_ZONE, 10, 100, 5, 40), gameManager);
+        ItemSpawner itemSpawner1 = new ItemSpawner(ItemType.BEER, new SpawnRule(Area.FANCYHOUSE_ZONE, 10, 12, 2, 50), gameManager);
+        ItemSpawner itemSpawner2 = new ItemSpawner(ItemType.BEER, new SpawnRule(Area.HOUSE_ZONE, 10, 12, 2, 50), gameManager);
 
         entityManager.addEntity(itemSpawner);
         entityManager.addEntity(itemSpawner1);
         entityManager.addEntity(itemSpawner2);
 
-
-        Main.startUpMessage("Adding Tree Berserkers");
-        entityManager.addEntity(new NpcSpawner(new TreeBerserker(gameManager, new Loot(2, 5, Sets.<Item>newHashSet())), Sets.newHashSet(Area.NEWBIE_ZONE, Area.NORTH1_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-
-        Main.startUpMessage("Adding Swamp Berserkers");
-        entityManager.addEntity(new NpcSpawner(new SwampBerserker(gameManager, new Loot(4, 10, Sets.<Item>newHashSet())), Sets.newHashSet(Area.NORTH2_ZONE), gameManager, new SpawnRule(10, 8, 2, 100)));
-
-        Main.startUpMessage("Adding Berg Orcs");
-        entityManager.addEntity(new NpcSpawner(new BergOrc(gameManager, new Loot(4, 10, Sets.<Item>newHashSet())), Sets.newHashSet(Area.BLOODRIDGE1_ZONE), gameManager, new SpawnRule(10, 8, 2, 100)));
-
-        Main.startUpMessage("Adding Red-Eyed Bears");
-        entityManager.addEntity(new NpcSpawner(new RedEyedBear(gameManager, new Loot(8, 13, Sets.<Item>newHashSet())), Sets.newHashSet(Area.TOFT1_ZONE), gameManager, new SpawnRule(10, 14, 3, 100)));
-        entityManager.addEntity(new NpcSpawner(new RedEyedBear(gameManager, new Loot(8, 13, Sets.<Item>newHashSet())), Sets.newHashSet(Area.TOFT2_ZONE), gameManager, new SpawnRule(10, 14, 3, 100)));
-        entityManager.addEntity(new NpcSpawner(new RedEyedBear(gameManager, new Loot(8, 13, Sets.<Item>newHashSet())), Sets.newHashSet(Area.RADIO_ROOM), gameManager, new SpawnRule(10, 1, 1, 10)));
-
-
-        Main.startUpMessage("Adding Swamp Bears");
-        entityManager.addEntity(new NpcSpawner(new SwampBear(gameManager, new Loot(9, 14, Sets.<Item>newHashSet())), Sets.newHashSet(Area.NORTH3_ZONE), gameManager, new SpawnRule(10, 12, 3, 100)));
-        entityManager.addEntity(new NpcSpawner(new SwampBear(gameManager, new Loot(9, 14, Sets.<Item>newHashSet())), Sets.newHashSet(Area.NORTH4_ZONE), gameManager, new SpawnRule(10, 12, 3, 100)));
-
-        Main.startUpMessage("Adding Gray Ekimmus");
-        entityManager.addEntity(new NpcSpawner(new GrayEkimmu(gameManager, new Loot(14, 17, Sets.<Item>newHashSet())), Sets.newHashSet(Area.NORTH4_ZONE), gameManager, new SpawnRule(10, 12, 3, 100)));
-        entityManager.addEntity(new NpcSpawner(new GrayEkimmu(gameManager, new Loot(14, 17, Sets.<Item>newHashSet())), Sets.newHashSet(Area.NORTH5_ZONE), gameManager, new SpawnRule(10, 12, 3, 100)));
-
-        Main.startUpMessage("Adding Stealth Panthers");
-        entityManager.addEntity(new NpcSpawner(new StealthPanther(gameManager, new Loot(14, 22, Sets.<Item>newHashSet())), Sets.newHashSet(Area.NORTH5_ZONE), gameManager, new SpawnRule(10, 12, 3, 100)));
-        entityManager.addEntity(new NpcSpawner(new StealthPanther(gameManager, new Loot(14, 22, Sets.<Item>newHashSet())), Sets.newHashSet(Area.NORTH6_ZONE), gameManager, new SpawnRule(10, 12, 3, 100)));
-
-        Main.startUpMessage("Adding Phantom Knights");
-
-        PhantomKnight phantomKnight = new PhantomKnight(gameManager, new Loot(18, 26, Sets.<Item>newHashSet()));
-        entityManager.addEntity(new NpcSpawner(phantomKnight, Sets.newHashSet(Area.BLOODRIDGE5_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(phantomKnight, Sets.newHashSet(Area.BLOODRIDGE6_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(phantomKnight, Sets.newHashSet(Area.BLOODRIDGE7_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-
-
-        PhantomOrc phantomOrc = new PhantomOrc(gameManager, new Loot(16, 24, Sets.<Item>newHashSet()));
-        Main.startUpMessage("Adding Phantom Orcs");
-        entityManager.addEntity(new NpcSpawner(phantomOrc, Sets.newHashSet(Area.BLOODRIDGE4_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(phantomOrc, Sets.newHashSet(Area.BLOODRIDGE4_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-
-        PhantomWizard phantomWizard = new PhantomWizard(gameManager, new Loot(16, 24, Sets.<Item>newHashSet()));
-        Main.startUpMessage("Adding Phantom Wizards");
-        entityManager.addEntity(new NpcSpawner(phantomWizard, Sets.newHashSet(Area.BLOODRIDGE4_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(phantomWizard, Sets.newHashSet(Area.BLOODRIDGE5_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-
-        Main.startUpMessage("Adding Demon Succubi");
-        DemonSuccubus demonSuccubus = new DemonSuccubus(gameManager, new Loot(120, 180, Sets.<Item>newHashSet()));
-        entityManager.addEntity(new NpcSpawner(demonSuccubus, Sets.newHashSet(Area.WESTERN9_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(demonSuccubus, Sets.newHashSet(Area.WESTERN10_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-
-        Main.startUpMessage("Adding Death Griffins");
-        DeathGriffin deathGriffin = new DeathGriffin(gameManager, new Loot(60, 80, Sets.<Item>newHashSet()));
-        entityManager.addEntity(new NpcSpawner(deathGriffin, Sets.newHashSet(Area.WESTERN8_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(deathGriffin, Sets.newHashSet(Area.WESTERN9_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-
-        Main.startUpMessage("Adding Nightmare Trolls");
-        NightmareTroll nightmareTroll = new NightmareTroll(gameManager, new Loot(18, 26, Sets.<Item>newHashSet()));
-        entityManager.addEntity(new NpcSpawner(nightmareTroll, Sets.newHashSet(Area.NORTH7_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(nightmareTroll, Sets.newHashSet(Area.NORTH8_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-
-        Main.startUpMessage("Adding Tiger Monoceruses");
-        TigerMonocerus tigerMonocerus = new TigerMonocerus(gameManager, new Loot(20, 29, Sets.<Item>newHashSet()));
-        entityManager.addEntity(new NpcSpawner(tigerMonocerus, Sets.newHashSet(Area.NORTH8_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(tigerMonocerus, Sets.newHashSet(Area.NORTH9_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-
-        Main.startUpMessage("Adding Razor-claw Wolves");
-        RazorClawWolf razorClawWolf = new RazorClawWolf(gameManager, new Loot(18, 26, Sets.<Item>newHashSet()));
-        entityManager.addEntity(new NpcSpawner(razorClawWolf, Sets.newHashSet(Area.TOFT2_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(razorClawWolf, Sets.newHashSet(Area.TOFT3_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-
-
-        Main.startUpMessage("Adding Black-hooded Wizards");
-        BlackHoodedWizard blackHoodedWizard = new BlackHoodedWizard(gameManager, new Loot(55, 74, Sets.<Item>newHashSet()));
-        entityManager.addEntity(new NpcSpawner(blackHoodedWizard, Sets.newHashSet(Area.TISLAND4_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(blackHoodedWizard, Sets.newHashSet(Area.TISLAND3_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-
-
-        Main.startUpMessage("Adding Tunnel Cobras");
-        TunnelCobra tunnelCobra = new TunnelCobra(gameManager, new Loot(40, 52, Sets.<Item>newHashSet()));
-        entityManager.addEntity(new NpcSpawner(tunnelCobra, Sets.newHashSet(Area.TISLAND3_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(tunnelCobra, Sets.newHashSet(Area.TISLAND4_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-
-        Main.startUpMessage("Adding Stone Giants");
-        StoneGiant stoneGiant = new StoneGiant(gameManager, new Loot(55, 69, Sets.<Item>newHashSet()));
-        entityManager.addEntity(new NpcSpawner(stoneGiant, Sets.newHashSet(Area.TISLAND4_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(stoneGiant, Sets.newHashSet(Area.TISLAND5_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-
-        Main.startUpMessage("Adding Scaled Deathcrawlers");
-        ScaledDeathcrawler scaledDeathcrawler = new ScaledDeathcrawler(gameManager, new Loot(150, 300, Sets.<Item>newHashSet()));
-        entityManager.addEntity(new NpcSpawner(scaledDeathcrawler, Sets.newHashSet(Area.NORTH10_ZONE), gameManager, new SpawnRule(10, 6, 2, 100)));
-        entityManager.addEntity(new NpcSpawner(scaledDeathcrawler, Sets.newHashSet(Area.NORTH11_ZONE), gameManager, new SpawnRule(10, 14, 2, 100)));
-
         Map<Integer, MerchantItemForSale> itemsForSale = Maps.newLinkedHashMap();
         itemsForSale.put(1, new MerchantItemForSale(ItemType.BEER, 1));
         itemsForSale.put(2, new MerchantItemForSale(ItemType.BROAD_SWORD, 1000));
diff --git a/src/main/java/com/comandante/creeper/Items/Item.java b/src/main/java/com/comandante/creeper/Items/Item.java
index d659383493cf650a9a085372706e98abad6729fc..575cc6043676a3071d83f16edb3c97cadcce8c85 100644
--- a/src/main/java/com/comandante/creeper/Items/Item.java
+++ b/src/main/java/com/comandante/creeper/Items/Item.java
@@ -119,4 +119,21 @@ public class Item implements Serializable {
     public Equipment getEquipment() {
         return equipment;
     }
+
+    @Override
+    public String toString() {
+        return "Item{" +
+                "itemName='" + itemName + '\'' +
+                ", itemDescription='" + itemDescription + '\'' +
+                ", itemTriggers=" + itemTriggers +
+                ", restingName='" + restingName + '\'' +
+                ", itemId='" + itemId + '\'' +
+                ", itemTypeId=" + itemTypeId +
+                ", numberOfUses=" + numberOfUses +
+                ", isWithPlayer=" + isWithPlayer +
+                ", loot=" + loot +
+                ", itemHalfLifeTicks=" + itemHalfLifeTicks +
+                ", equipment=" + equipment +
+                '}';
+    }
 }
diff --git a/src/main/java/com/comandante/creeper/Items/Loot.java b/src/main/java/com/comandante/creeper/Items/Loot.java
index 1bcc813e791ea3d96126759500aebea7142e61de..d4891cc0a5308eb617ab27c03024fd7bf2596484 100644
--- a/src/main/java/com/comandante/creeper/Items/Loot.java
+++ b/src/main/java/com/comandante/creeper/Items/Loot.java
@@ -26,4 +26,13 @@ public class Loot implements Serializable {
     public int getLootGoldMin() {
         return lootGoldMin;
     }
+
+    @Override
+    public String toString() {
+        return "Loot{" +
+                "items=" + items +
+                ", lootGoldMax=" + lootGoldMax +
+                ", lootGoldMin=" + lootGoldMin +
+                '}';
+    }
 }
diff --git a/src/main/java/com/comandante/creeper/entity/CreeperEntity.java b/src/main/java/com/comandante/creeper/entity/CreeperEntity.java
index 3a121db792d349022585e10f910c5f7bf839da1f..9b4e3ea4b2389840941b32174bf80d953d6fa161 100644
--- a/src/main/java/com/comandante/creeper/entity/CreeperEntity.java
+++ b/src/main/java/com/comandante/creeper/entity/CreeperEntity.java
@@ -1,5 +1,7 @@
 package com.comandante.creeper.entity;
 
+import com.google.gson.annotations.Expose;
+
 import java.util.UUID;
 
 public abstract class CreeperEntity implements Runnable {
diff --git a/src/main/java/com/comandante/creeper/npc/Npc.java b/src/main/java/com/comandante/creeper/npc/Npc.java
index 040fdc4a5aa17a7e3cf53bab04eefa13525a0fc8..8aae23e8227890eb6e4e0069703f8721a08f8c85 100644
--- a/src/main/java/com/comandante/creeper/npc/Npc.java
+++ b/src/main/java/com/comandante/creeper/npc/Npc.java
@@ -2,13 +2,20 @@ package com.comandante.creeper.npc;
 
 
 import com.comandante.creeper.Items.Item;
+import com.comandante.creeper.Items.ItemType;
 import com.comandante.creeper.Items.Loot;
 import com.comandante.creeper.entity.CreeperEntity;
 import com.comandante.creeper.managers.GameManager;
+import com.comandante.creeper.spawner.SpawnRule;
 import com.comandante.creeper.stat.Stats;
+import com.comandante.creeper.stat.StatsAdapter;
+import com.comandante.creeper.stat.StatsBuilder;
 import com.comandante.creeper.world.Area;
 import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
 import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.annotations.Expose;
 
 import java.util.HashSet;
 import java.util.Random;
@@ -19,19 +26,7 @@ import static com.comandante.creeper.server.Color.RED;
 import static com.comandante.creeper.server.Color.RESET;
 
 
-public abstract class Npc extends CreeperEntity {
-
-    public static void main(String[] args) {
-        Gson gson = new Gson();
-
-        String s = gson.toJson(Item.class);
-        System.out.println(s);
-
-    }
-
-    public void setLastPhraseTimestamp(long lastPhraseTimestamp) {
-        this.lastPhraseTimestamp = lastPhraseTimestamp;
-    }
+public class Npc extends CreeperEntity {
 
     private long lastPhraseTimestamp;
     private final GameManager gameManager;
@@ -39,14 +34,25 @@ public abstract class Npc extends CreeperEntity {
     private final String colorName;
     private final Stats stats;
     private final String dieMessage;
-    private Set<Area> roamAreas;
+    private final Set<Area> roamAreas;
     private final Set<String> validTriggers;
     private final Loot loot;
+    private final Set<SpawnRule> spawnRules;
+    private final AtomicBoolean isInFight = new AtomicBoolean(false);
+    private final Random random = new Random();
 
-    private AtomicBoolean isInFight = new AtomicBoolean(false);
-    Random random = new Random();
-
-    public abstract Npc create(GameManager gameManager, Loot loot);
+    protected Npc(GameManager gameManager, String name, String colorName, long lastPhraseTimestamp, Stats stats, String dieMessage, Set<Area> roamAreas, Set<String> validTriggers, Loot loot, Set<SpawnRule> spawnRules) {
+        this.gameManager = gameManager;
+        this.name = name;
+        this.colorName = colorName;
+        this.lastPhraseTimestamp = lastPhraseTimestamp;
+        this.stats = stats;
+        this.dieMessage = dieMessage;
+        this.roamAreas = roamAreas;
+        this.validTriggers = validTriggers;
+        this.loot = loot;
+        this.spawnRules = spawnRules;
+    }
 
     @Override
     public void run() {
@@ -58,20 +64,12 @@ public abstract class Npc extends CreeperEntity {
         }
     }
 
-    public String getColorName() {
-        return colorName;
+    public void setLastPhraseTimestamp(long lastPhraseTimestamp) {
+        this.lastPhraseTimestamp = lastPhraseTimestamp;
     }
 
-    protected Npc(GameManager gameManager, String name, String colorName, long lastPhraseTimestamp, Stats stats, String dieMessage, Set<Area> roamAreas, Set<String> validTriggers, Loot loot) {
-        this.gameManager = gameManager;
-        this.name = name;
-        this.colorName = colorName;
-        this.lastPhraseTimestamp = lastPhraseTimestamp;
-        this.stats = stats;
-        this.dieMessage = dieMessage;
-        this.roamAreas = roamAreas;
-        this.validTriggers = validTriggers;
-        this.loot = loot;
+    public String getColorName() {
+        return colorName;
     }
 
     public Set<String> getValidTriggers() {
@@ -125,7 +123,7 @@ public abstract class Npc extends CreeperEntity {
         return random.nextInt((max - min) + 1) + min;
     }
 
-    public void setRoamAreas(Set<Area> roamAreas) {
-        this.roamAreas = roamAreas;
+    public Set<SpawnRule> getSpawnRules() {
+        return spawnRules;
     }
 }
diff --git a/src/main/java/com/comandante/creeper/npc/NpcAdapter.java b/src/main/java/com/comandante/creeper/npc/NpcAdapter.java
index 96e291be244915fd00df1f57263bc3f8cba11f89..3417095c4e0961bea8465a456616be21e3512eae 100644
--- a/src/main/java/com/comandante/creeper/npc/NpcAdapter.java
+++ b/src/main/java/com/comandante/creeper/npc/NpcAdapter.java
@@ -1,7 +1,224 @@
 package com.comandante.creeper.npc;
 
-/**
- * Created by kearney on 5/13/15.
- */
-public class NpcAdapter {
+import com.comandante.creeper.Items.Item;
+import com.comandante.creeper.Items.ItemType;
+import com.comandante.creeper.Items.Loot;
+import com.comandante.creeper.managers.GameManager;
+import com.comandante.creeper.spawner.SpawnRule;
+import com.comandante.creeper.stat.StatsBuilder;
+import com.comandante.creeper.world.Area;
+import com.google.common.collect.Sets;
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+
+public class NpcAdapter extends TypeAdapter<Npc> {
+
+    private final GameManager gameManager;
+
+    public NpcAdapter(GameManager gameManager) {
+        this.gameManager = gameManager;
+    }
+
+    @Override
+    public void write(JsonWriter jsonWriter, Npc npc) throws IOException {
+        jsonWriter.beginObject();
+        jsonWriter.name("name").value(npc.getName());
+        jsonWriter.name("colorName").value(npc.getColorName());
+        jsonWriter.name("dieMessage").value(npc.getDieMessage());
+
+        Loot loot = npc.getLoot();
+        jsonWriter.name("loot");
+        jsonWriter.beginObject();
+        jsonWriter.name("lootGoldMin").value(npc.getLoot().getLootGoldMin());
+        jsonWriter.name("lootGoldMax").value(npc.getLoot().getLootGoldMax());
+        jsonWriter.name("lootItems");
+        jsonWriter.beginArray();
+        for (Item item : loot.getItems()) {
+            jsonWriter.value(item.getItemTypeId());
+        }
+        jsonWriter.endArray();
+        jsonWriter.endObject();
+
+        jsonWriter.name("roamAreas");
+        jsonWriter.beginArray();
+        for (Area area : npc.getRoamAreas()) {
+            jsonWriter.value(area.getName());
+        }
+        jsonWriter.endArray();
+
+        jsonWriter.name("stats");
+        jsonWriter.beginObject();
+        jsonWriter.name("agile").value(npc.getStats().getAgile());
+        jsonWriter.name("aim").value(npc.getStats().getAim());
+        jsonWriter.name("armorRating").value(npc.getStats().getArmorRating());
+        jsonWriter.name("currentHealth").value(npc.getStats().getCurrentHealth());
+        jsonWriter.name("currentMana").value(npc.getStats().getCurrentMana());
+        jsonWriter.name("experience").value(npc.getStats().getExperience());
+        jsonWriter.name("maxHealth").value(npc.getStats().getMaxHealth());
+        jsonWriter.name("maxMana").value(npc.getStats().getMaxMana());
+        jsonWriter.name("meleSkill").value(npc.getStats().getMeleSkill());
+        jsonWriter.name("numberOfWeaponRolls").value(npc.getStats().getNumberOfWeaponRolls());
+        jsonWriter.name("strength").value(npc.getStats().getStrength());
+        jsonWriter.name("weaponRatingMax").value(npc.getStats().getWeaponRatingMax());
+        jsonWriter.name("weaponRatingMin").value(npc.getStats().getWeaponRatingMin());
+        jsonWriter.name("willPower").value(npc.getStats().getWillpower());
+        jsonWriter.endObject();
+
+        jsonWriter.name("spawnAreas");
+        jsonWriter.beginObject();
+        for (SpawnRule spawnRule : npc.getSpawnRules()) {
+            jsonWriter.name(spawnRule.getArea().getName());
+            jsonWriter.beginObject();
+            jsonWriter.name("randomChance").value(spawnRule.getRandomChance());
+            jsonWriter.name("maxPerRoom").value(spawnRule.getMaxPerRoom());
+            jsonWriter.name("spawnIntervalTicks").value(spawnRule.getSpawnIntervalTicks());
+            jsonWriter.name("maxInstances").value(spawnRule.getMaxInstances());
+            jsonWriter.endObject();
+        }
+        jsonWriter.endObject();
+
+        jsonWriter.name("validTriggers");
+        jsonWriter.beginArray();
+        for (String trigger : npc.getValidTriggers()) {
+            jsonWriter.value(trigger);
+        }
+        jsonWriter.endArray();
+
+
+        jsonWriter.endObject();
+
+    }
+
+    @Override
+    public Npc read(JsonReader jsonReader) throws IOException {
+
+        jsonReader.beginObject();
+        jsonReader.nextName();
+        final String npcName = jsonReader.nextString();
+        jsonReader.nextName();
+        final String npcColorName = jsonReader.nextString();
+        jsonReader.nextName();
+        final String npcDieMessage = jsonReader.nextString();
+        jsonReader.nextName();
+        jsonReader.beginObject();
+        jsonReader.nextName();
+        final int lootGoldMin = jsonReader.nextInt();
+        jsonReader.nextName();
+        final int lootGoldMax = jsonReader.nextInt();
+        jsonReader.nextName();
+        jsonReader.beginArray();
+        Set<Item> items = Sets.newHashSet();
+        while (jsonReader.hasNext()) {
+            items.add(ItemType.itemTypeFromCode(jsonReader.nextInt()).create());
+        }
+        jsonReader.endArray();
+        Loot loot = new Loot(lootGoldMin, lootGoldMax, items);
+        jsonReader.endObject();
+
+        jsonReader.nextName();
+        jsonReader.beginArray();
+        Set<Area> roamAreas = Sets.newHashSet();
+        while (jsonReader.hasNext()) {
+            roamAreas.add(Area.getByName(jsonReader.nextString()));
+        }
+        jsonReader.endArray();
+
+        jsonReader.nextName();
+        jsonReader.beginObject();
+        StatsBuilder statsBuilder = new StatsBuilder();
+
+        jsonReader.nextName();
+        statsBuilder.setAgile(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setAim(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setArmorRating(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setCurrentHealth(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setCurrentMana(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setExperience(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setMaxHealth(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setMaxMana(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setMeleSkill(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setNumberOfWeaponRolls(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setStrength(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setWeaponRatingMax(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setWeaponRatingMin(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setWillpower(jsonReader.nextInt());
+        jsonReader.endObject();
+
+        jsonReader.nextName();
+        jsonReader.beginObject();
+        Set<SpawnRule> spawnRules = Sets.newHashSet();
+        while (jsonReader.hasNext()) {
+            String spawnAreaName = jsonReader.nextName();
+            jsonReader.beginObject();
+            jsonReader.nextName();
+
+            int randomChance = jsonReader.nextInt();
+            jsonReader.nextName();
+
+            int maxPerRoom = jsonReader.nextInt();
+            jsonReader.nextName();
+
+            int spawnIntervalTicks = jsonReader.nextInt();
+            jsonReader.nextName();
+
+            int maxInstances = jsonReader.nextInt();
+            jsonReader.endObject();
+            spawnRules.add(new SpawnRule(Area.getByName(spawnAreaName),spawnIntervalTicks, maxInstances, maxPerRoom, randomChance));
+        }
+        jsonReader.endObject();
+
+        jsonReader.nextName();
+        jsonReader.beginArray();
+        Set<String> validTriggers = Sets.newHashSet();
+        while (jsonReader.hasNext()) {
+            validTriggers.add(jsonReader.nextString());
+        }
+        jsonReader.endArray();
+        jsonReader.endObject();
+
+        NpcBuilder npcBuilder = new NpcBuilder()
+                .setColorName(npcColorName)
+                .setDieMessage(npcDieMessage)
+                .setLoot(loot)
+                .setName(npcName)
+                .setRoamAreas(roamAreas)
+                .setSpawnRules(spawnRules)
+                .setStats(statsBuilder.createStats())
+                .setValidTriggers(validTriggers)
+                .setGameManager(gameManager);
+
+        return npcBuilder.createNpc();
+    }
 }
diff --git a/src/main/java/com/comandante/creeper/npc/NpcAdapterTest.java b/src/main/java/com/comandante/creeper/npc/NpcAdapterTest.java
index 608ad563001b4561b08f70ced14f672c618daf1a..e3c7afdba39cbcaf71333d4d88977ca4577aa645 100644
--- a/src/main/java/com/comandante/creeper/npc/NpcAdapterTest.java
+++ b/src/main/java/com/comandante/creeper/npc/NpcAdapterTest.java
@@ -1,16 +1,102 @@
 package com.comandante.creeper.npc;
 
+import com.comandante.creeper.Items.Item;
+import com.comandante.creeper.Items.ItemType;
+import com.comandante.creeper.Items.Loot;
+import com.comandante.creeper.spawner.SpawnRule;
+import com.comandante.creeper.stat.Stats;
+import com.comandante.creeper.stat.StatsBuilder;
+import com.comandante.creeper.world.Area;
+import com.google.common.collect.Sets;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Random;
+import java.util.Set;
+import java.util.UUID;
 
 import static org.junit.Assert.*;
 
-/**
- * Created by kearney on 5/14/15.
- */
 public class NpcAdapterTest {
 
+    Npc npcOne;
+    Gson gson;
+
     @Before
     public void setUp() throws Exception {
 
+        final GsonBuilder gsonBuilder = new GsonBuilder();
+        gsonBuilder.registerTypeAdapter(Npc.class, new NpcAdapter(null));
+
+        gsonBuilder.setPrettyPrinting();
+        gson = gsonBuilder.create();
+
+        Random randomGenerator = new Random();
+
+        Stats npcOneStats = new StatsBuilder()
+                .setAgile(randomGenerator.nextInt(100))
+                .setAim(randomGenerator.nextInt(100))
+                .setArmorRating(randomGenerator.nextInt(100))
+                .setCurrentHealth(randomGenerator.nextInt(100))
+                .setCurrentMana(randomGenerator.nextInt(100))
+                .setExperience(randomGenerator.nextInt(100))
+                .setMaxHealth(randomGenerator.nextInt(100))
+                .setMaxMana(randomGenerator.nextInt(100))
+                .setMeleSkill(randomGenerator.nextInt(100))
+                .setNumberOfWeaponRolls(randomGenerator.nextInt(100))
+                .setStrength(randomGenerator.nextInt(100))
+                .setWeaponRatingMax(randomGenerator.nextInt(100))
+                .setWeaponRatingMin(randomGenerator.nextInt(100))
+                .setWillpower(randomGenerator.nextInt(100))
+                .createStats();
+
+        Loot npcOneLoot = new Loot(randomGenerator.nextInt(100), randomGenerator.nextInt(100), Sets.newHashSet(ItemType.BEER.create()));
+        SpawnRule npcOneSpawnRule1 = new SpawnRule(Area.BLOODRIDGE10_ZONE, randomGenerator.nextInt(100), randomGenerator.nextInt(100), randomGenerator.nextInt(100), randomGenerator.nextInt(100));
+        SpawnRule npcOneSpawnRule2 = new SpawnRule(Area.BLOODRIDGE10_ZONE, randomGenerator.nextInt(100), randomGenerator.nextInt(100), randomGenerator.nextInt(100), randomGenerator.nextInt(100));
+        npcOne = new NpcBuilder()
+                .setColorName(UUID.randomUUID().toString())
+                .setDieMessage(UUID.randomUUID().toString())
+                .setName(UUID.randomUUID().toString())
+                .setStats(npcOneStats)
+                .setLoot(npcOneLoot)
+                .setRoamAreas(Sets.newHashSet(Area.BLOODRIDGE10_ZONE, Area.BLOODRIDGE11_ZONE))
+                .setSpawnRules(Sets.newHashSet(npcOneSpawnRule1, npcOneSpawnRule2))
+                .setValidTriggers(Sets.newHashSet(UUID.randomUUID().toString(), UUID.randomUUID().toString()))
+                .createNpc();
+    }
+
+    @Test
+    public void testSerializeDeSerialize() throws Exception {
+
+
+        String npcOneJson = gson.toJson(npcOne);
+        System.out.println(npcOneJson);
+
+        Npc npc = gson.fromJson(npcOneJson, Npc.class);
+
+        assertEquals(npcOne.getDieMessage(), npc.getDieMessage());
+        assertEquals(npcOne.getColorName(), npc.getColorName());
+        assertEquals(npcOne.getName(), npc.getName());
+
+        assertEquals(npcOne.getLoot().getLootGoldMax(), npc.getLoot().getLootGoldMax());
+        assertEquals(npcOne.getLoot().getLootGoldMin(), npc.getLoot().getLootGoldMin());
+        Set<Item> items = npcOne.getLoot().getItems();
+        Item originalItem = null;
+        Item newItem = null;
+        for (Item item: items) {
+            originalItem = item;
+        }
+        items = npc.getLoot().getItems();
+        for (Item item: items) {
+            newItem = item;
+        }
+        assertEquals(originalItem.getItemDescription(), newItem.getItemDescription());
+        assertEquals(npcOne.getRoamAreas(), npc.getRoamAreas());
+
+
+        assertEquals(npcOne.getValidTriggers(), npc.getValidTriggers());
+
     }
 }
\ No newline at end of file
diff --git a/src/main/java/com/comandante/creeper/npc/NpcBuilder.java b/src/main/java/com/comandante/creeper/npc/NpcBuilder.java
index ea00417069278aa004dd9ef620139dd46dfc0c3e..7c8df499fdf6cbd6ce7e54be1f4601a866532369 100644
--- a/src/main/java/com/comandante/creeper/npc/NpcBuilder.java
+++ b/src/main/java/com/comandante/creeper/npc/NpcBuilder.java
@@ -20,6 +20,22 @@ public class NpcBuilder {
     private Loot loot;
     private Set<SpawnRule> spawnRules;
 
+    public NpcBuilder() {
+    }
+
+    public NpcBuilder(Npc npc) {
+        this.name = npc.getName();
+        this.colorName = npc.getColorName();
+        this.lastPhraseTimestamp = npc.getLastPhraseTimestamp();
+        this.stats = npc.getStats();
+        this.dieMessage = npc.getDieMessage();
+        this.roamAreas = npc.getRoamAreas();
+        this.validTriggers = npc.getValidTriggers();
+        this.loot = npc.getLoot();
+        this.spawnRules = npc.getSpawnRules();
+        this.gameManager = npc.getGameManager();
+    }
+
     public NpcBuilder setGameManager(GameManager gameManager) {
         this.gameManager = gameManager;
         return this;
diff --git a/src/main/java/com/comandante/creeper/npc/NpcExporter.java b/src/main/java/com/comandante/creeper/npc/NpcExporter.java
index e87931a7924d0c6ee891688f0edf6193fe1c5e10..a6e89942391fbdf63d25558a09bcbab50473b624 100644
--- a/src/main/java/com/comandante/creeper/npc/NpcExporter.java
+++ b/src/main/java/com/comandante/creeper/npc/NpcExporter.java
@@ -1,7 +1,23 @@
 package com.comandante.creeper.npc;
 
-/**
- * Created by kearney on 5/14/15.
- */
+
+import com.comandante.creeper.managers.GameManager;
+import com.comandante.creeper.world.WorldModel;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+import com.google.gson.GsonBuilder;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.nio.charset.Charset;
+import java.util.List;
+
 public class NpcExporter {
+
+    public static List<Npc> getNpcsFromFile(GameManager gameManager) throws FileNotFoundException {
+        final GsonBuilder gsonBuilder = new GsonBuilder();
+        gsonBuilder.registerTypeAdapter(Npc.class, new NpcAdapter(gameManager));
+        Npc npc = gsonBuilder.create().fromJson(Files.newReader(new File(("world/npcs/streethustler.json")), Charset.defaultCharset()), Npc.class);
+        return Lists.newArrayList(npc);
+    }
 }
diff --git a/src/main/java/com/comandante/creeper/spawner/ItemSpawner.java b/src/main/java/com/comandante/creeper/spawner/ItemSpawner.java
index 51a01f3be135b0ae59ace70b3e8227b183eaa1ea..2ac14fe14c63d4f827f6b40d3ccef15f378ee9ce 100644
--- a/src/main/java/com/comandante/creeper/spawner/ItemSpawner.java
+++ b/src/main/java/com/comandante/creeper/spawner/ItemSpawner.java
@@ -27,12 +27,12 @@ public class ItemSpawner extends CreeperEntity {
     private final Area spawnArea;
 
 
-    public ItemSpawner(ItemType spawnItemType, Area area, SpawnRule spawnRule, GameManager gameManager) {
+    public ItemSpawner(ItemType spawnItemType, SpawnRule spawnRule, GameManager gameManager) {
         this.spawnItemType = spawnItemType;
         this.spawnRule = spawnRule;
         this.gameManager = gameManager;
         this.noTicks = spawnRule.getSpawnIntervalTicks();
-        this.spawnArea = area;
+        this.spawnArea = spawnRule.getArea();
     }
 
     public void incTicks() {
diff --git a/src/main/java/com/comandante/creeper/spawner/NpcSpawner.java b/src/main/java/com/comandante/creeper/spawner/NpcSpawner.java
index eb555787211ee2bc438149f0160019f5bf4b0144..c116b558743dac5912f760e90e36e4ab7c3fbd5e 100644
--- a/src/main/java/com/comandante/creeper/spawner/NpcSpawner.java
+++ b/src/main/java/com/comandante/creeper/spawner/NpcSpawner.java
@@ -6,6 +6,7 @@ import com.comandante.creeper.Main;
 import com.comandante.creeper.entity.CreeperEntity;
 import com.comandante.creeper.managers.GameManager;
 import com.comandante.creeper.npc.Npc;
+import com.comandante.creeper.npc.NpcBuilder;
 import com.comandante.creeper.world.Area;
 import com.comandante.creeper.world.Room;
 import com.google.common.base.Predicate;
@@ -23,12 +24,10 @@ public class NpcSpawner extends CreeperEntity {
     private final SpawnRule spawnRule;
     private int noTicks;
     private final Random random = new Random();
-    private final Set<Area> spawnAreas;
 
 
-    public NpcSpawner(Npc npc, Set<Area> area, GameManager gameManager, SpawnRule spawnRule) {
+    public NpcSpawner(Npc npc, GameManager gameManager, SpawnRule spawnRule) {
         this.npc = npc;
-        this.spawnAreas = area;
         this.gameManager = gameManager;
         this.spawnRule = spawnRule;
         this.noTicks = spawnRule.getSpawnIntervalTicks();
@@ -42,13 +41,11 @@ public class NpcSpawner extends CreeperEntity {
     public void run() {
         incTicks();
         if (noTicks >= spawnRule.getSpawnIntervalTicks()) {
-            for (Area spawnArea : spawnAreas) {
-                int randomPercentage = spawnRule.getRandomChance();
-                int numberOfAttempts = spawnRule.getMaxInstances() - counterNumberInArea(spawnArea);
-                for (int i = 0; i < numberOfAttempts; i++) {
-                    if (random.nextInt(100) < randomPercentage || randomPercentage == 100) {
-                        createAndAddItem(spawnArea);
-                    }
+            int randomPercentage = spawnRule.getRandomChance();
+            int numberOfAttempts = spawnRule.getMaxInstances() - counterNumberInArea(spawnRule.getArea());
+            for (int i = 0; i < numberOfAttempts; i++) {
+                if (random.nextInt(100) < randomPercentage || randomPercentage == 100) {
+                    createAndAddItem(spawnRule.getArea());
                 }
             }
             noTicks = 0;
@@ -74,7 +71,8 @@ public class NpcSpawner extends CreeperEntity {
     private void createAndAddItem(Area spawnArea) {
         ArrayList<Room> rooms = Lists.newArrayList(Iterators.filter(gameManager.getRoomManager().getRoomsByArea(spawnArea).iterator(), getRoomsWithRoom()));
         Room room = rooms.get(random.nextInt(rooms.size()));
-        Npc newNpc = npc.create(gameManager, npc.getLoot());
+        NpcBuilder npcBuilder = new NpcBuilder(npc);
+        Npc newNpc = npcBuilder.createNpc();
         gameManager.getEntityManager().addEntity(newNpc);
         room.addPresentNpc(newNpc.getEntityId());
         Main.metrics.counter(MetricRegistry.name(NpcSpawner.class, npc.getName() + "-spawn")).inc();
diff --git a/src/main/java/com/comandante/creeper/spawner/SpawnRule.java b/src/main/java/com/comandante/creeper/spawner/SpawnRule.java
index c2dea9828acf3186b5d2463300ef05a610d7b6fe..8dc0d93839e96e99c35a39ad0994614aca69661f 100644
--- a/src/main/java/com/comandante/creeper/spawner/SpawnRule.java
+++ b/src/main/java/com/comandante/creeper/spawner/SpawnRule.java
@@ -1,13 +1,17 @@
 package com.comandante.creeper.spawner;
 
+import com.comandante.creeper.world.Area;
+
 public class SpawnRule {
 
+    private final Area area;
     private int randomChance;
     private final int spawnIntervalTicks;
     private final int maxInstances;
     private final int maxPerRoom;
 
-    public SpawnRule(int spawnIntervalTicks, int maxInstances, int maxPerRoom, int randomPercent) {
+    public SpawnRule(Area area, int spawnIntervalTicks, int maxInstances, int maxPerRoom, int randomPercent) {
+        this.area = area;
         this.spawnIntervalTicks = spawnIntervalTicks;
         this.maxInstances = maxInstances;
         this.maxPerRoom = maxPerRoom;
@@ -29,5 +33,20 @@ public class SpawnRule {
     public int getMaxInstances() {
         return maxInstances;
     }
+
+    public Area getArea() {
+        return area;
+    }
+
+    @Override
+    public String toString() {
+        return "SpawnRule{" +
+                "area=" + area +
+                ", randomChance=" + randomChance +
+                ", spawnIntervalTicks=" + spawnIntervalTicks +
+                ", maxInstances=" + maxInstances +
+                ", maxPerRoom=" + maxPerRoom +
+                '}';
+    }
 }
 
diff --git a/src/main/java/com/comandante/creeper/stat/StatsAdapter.java b/src/main/java/com/comandante/creeper/stat/StatsAdapter.java
index a1e080e976a845db3c49c712a359eb6a326894d2..afa67cfbff11c4e7d280283a4d970b3dfae3d5d1 100644
--- a/src/main/java/com/comandante/creeper/stat/StatsAdapter.java
+++ b/src/main/java/com/comandante/creeper/stat/StatsAdapter.java
@@ -1,7 +1,69 @@
 package com.comandante.creeper.stat;
 
-/**
- * Created by kearney on 5/14/15.
- */
-public class StatsAdapter {
+import com.comandante.creeper.npc.Npc;
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+import java.io.IOException;
+
+
+public class StatsAdapter extends TypeAdapter<Stats>  {
+
+    @Override
+    public void write(JsonWriter jsonWriter, Stats stats) throws IOException {
+
+    }
+
+    @Override
+    public Stats read(JsonReader jsonReader) throws IOException {
+
+        jsonReader.beginObject();
+        StatsBuilder statsBuilder = new StatsBuilder();
+
+        jsonReader.nextName();
+        statsBuilder.setAgile(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setAim(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setArmorRating(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setCurrentHealth(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setCurrentMana(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setExperience(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setMaxHealth(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setMaxMana(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setMeleSkill(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setNumberOfWeaponRolls(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setStrength(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setWeaponRatingMax(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setWeaponRatingMin(jsonReader.nextInt());
+
+        jsonReader.nextName();
+        statsBuilder.setWillpower(jsonReader.nextInt());
+        jsonReader.endObject();
+
+        return statsBuilder.createStats();
+    }
 }