update doc endpoints can cause 500
ast.literal_eval unable to parse json that has true or false. Since python uses True and False, the literal_eval fails when attempting to turn json strings into objects to merge. 

work around for now is to use string representations of values, for example, 'true' instead of true

diff --git a/lrs/objects/ActivityProfileManager.py b/lrs/objects/ActivityProfileManager.py
index d57c51f..0c8e300 100644
--- a/lrs/objects/ActivityProfileManager.py
+++ b/lrs/objects/ActivityProfileManager.py
@@ -32,8 +32,8 @@ class ActivityProfileManager():
                 p.updated = datetime.datetime.utcnow().replace(tzinfo=utc)
         else:
             etag.check_preconditions(request_dict,p, required=True)
-            orig_prof = ast.literal_eval(p.json_profile)
-            post_profile = ast.literal_eval(post_profile)
+            orig_prof = json.loads(p.json_profile)
+            post_profile = json.loads(post_profile)
             if not isinstance(post_profile, dict):
                 raise ParamError("The document was not able to be parsed into a JSON object.")
             else:
diff --git a/lrs/objects/ActivityStateManager.py b/lrs/objects/ActivityStateManager.py
index ec15746..78e07c4 100644
--- a/lrs/objects/ActivityStateManager.py
+++ b/lrs/objects/ActivityStateManager.py
@@ -46,8 +46,8 @@ class ActivityStateManager():
             if self.updated:
                 p.updated = self.updated
         else:
-            orig_state = ast.literal_eval(p.json_state)
-            post_state = ast.literal_eval(post_state)
+            orig_state = json.loads(p.json_state)
+            post_state = json.loads(post_state)
             if not isinstance(post_state, dict):
                 raise ParamError("The document was not able to be parsed into a JSON object.")
             else:
diff --git a/lrs/objects/AgentManager.py b/lrs/objects/AgentManager.py
index b3c439c..50d6a68 100644
--- a/lrs/objects/AgentManager.py
+++ b/lrs/objects/AgentManager.py
@@ -61,8 +61,8 @@ class AgentManager():
                 p.updated = datetime.datetime.utcnow().replace(tzinfo=utc)
         else:
             etag.check_preconditions(request_dict,p, required=True)
-            orig_prof = ast.literal_eval(p.json_profile)
-            post_profile = ast.literal_eval(post_profile)
+            orig_prof = json.loads(p.json_profile)
+            post_profile = json.loads(post_profile)
             if not isinstance(post_profile, dict):
                 raise ParamError("The document was not able to be parsed into a JSON object.")
             else:
diff --git a/lrs/tests/ActivityProfileTests.py b/lrs/tests/ActivityProfileTests.py
index 723f669..ab9bee7 100644
--- a/lrs/tests/ActivityProfileTests.py
+++ b/lrs/tests/ActivityProfileTests.py
@@ -396,3 +396,38 @@ class ActivityProfileTests(TestCase):
         
         theget = self.client.get(path, Authorization=self.auth, X_Experience_API_Version="1.0")
         self.assertEqual(theget['ETag'], '"d4827d99a5cc3510d3847baa341ba5a3b477fdfc"')
+
+    def test_json_merge(self):
+        prof = '{"test": { "goal": "ensure proper json parse", "attempt": 1, "result": null } }'
+
+        params = {"profileId": "prof:test_json_merge", "activityId": "act:test.json.merge.prof"}
+        path = '%s?%s' % (reverse(views.activity_profile), urllib.urlencode(params))
+        
+        post = self.client.post(path, prof, content_type="application/json", If_None_Match='*', Authorization=self.auth,  X_Experience_API_Version="1.0.0")
+        self.assertEqual(post.status_code, 204)
+        
+        get = self.client.get(path, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
+        self.assertEqual(get.status_code, 200)
+        returned = json.loads(get.content)
+        sent = json.loads(prof)
+        self.assertEqual(returned['test']['goal'], sent['test']['goal'])
+        self.assertEqual(returned['test']['attempt'], sent['test']['attempt'])
+        self.assertEqual(returned['test']['result'], sent['test']['result'])
+        etag = '"%s"' % hashlib.sha1(get.content).hexdigest()
+        self.assertEqual(get.get('etag'), etag)
+
+        sent['test']['result'] = True
+        sent['test']['attempt'] = sent['test']['attempt'] + 1
+        prof = json.dumps(sent)
+        post = self.client.post(path, prof, content_type="application/json", If_Match=etag, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
+        self.assertEqual(post.status_code, 204)
+
+        get = self.client.get(path, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
+        self.assertEqual(get.status_code, 200)
+        returned = json.loads(get.content)
+        sent = json.loads(prof)
+        self.assertEqual(returned['test']['goal'], sent['test']['goal'])
+        self.assertEqual(returned['test']['attempt'], sent['test']['attempt'])
+        self.assertEqual(returned['test']['result'], sent['test']['result'])
+        etag = '"%s"' % hashlib.sha1(get.content).hexdigest()
+        self.assertEqual(get.get('etag'), etag)
diff --git a/lrs/tests/AgentProfileTests.py b/lrs/tests/AgentProfileTests.py
index 613ee71..80bac65 100644
--- a/lrs/tests/AgentProfileTests.py
+++ b/lrs/tests/AgentProfileTests.py
@@ -342,12 +342,12 @@ class AgentProfileTests(TestCase):
         path = '%s?%s' % (reverse(views.agent_profile), urllib.urlencode(params))
         prof = {"test":"post updated profile","obj":{"agent":"mailto:test@example.com"}}
         
-        post = self.client.post(path, prof, content_type="application/json", Authorization=self.auth,  X_Experience_API_Version="1.0.0")
+        post = self.client.post(path, json.dumps(prof), content_type="application/json", Authorization=self.auth,  X_Experience_API_Version="1.0.0")
         self.assertEqual(post.status_code, 204)
         
         get = self.client.get(path, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
         self.assertEqual(get.status_code, 200)
-        self.assertEqual(ast.literal_eval(get.content), prof)
+        self.assertEqual(json.loads(get.content), prof)
         etag = '"%s"' % hashlib.sha1(get.content).hexdigest()
         self.assertEqual(get.get('etag'), etag)
 
@@ -355,15 +355,15 @@ class AgentProfileTests(TestCase):
         path = '%s?%s' % (reverse(views.agent_profile), urllib.urlencode(params))
         prof = {"obj":{"agent":"mailto:test@example.com", "new":"thing"}, "added":"yes"}
 
-        post = self.client.post(path, prof, content_type="application/json", Authorization=self.auth,  X_Experience_API_Version="1.0.0")
+        post = self.client.post(path, json.dumps(prof), content_type="application/json", Authorization=self.auth,  X_Experience_API_Version="1.0.0")
         self.assertEqual(post.status_code, 409)
         
-        post = self.client.post(path, prof, content_type="application/json",If_Match=etag, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
+        post = self.client.post(path, json.dumps(prof), content_type="application/json",If_Match=etag, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
         self.assertEqual(post.status_code, 204)
 
         get = self.client.get(path, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
         self.assertEqual(get.status_code, 200)
-        ret_json = ast.literal_eval(get.content)
+        ret_json = json.loads(get.content)
         self.assertEqual(ret_json['added'], prof['added'])
         self.assertEqual(ret_json['test'], "post updated profile")
         self.assertEqual(ret_json['obj']['agent'], prof['obj']['agent'])
@@ -377,12 +377,12 @@ class AgentProfileTests(TestCase):
         path = '%s?%s' % (reverse(views.agent_profile), urllib.urlencode(params))
         prof = {"test":"post and put profile","obj":{"agent":"mailto:test@example.com"}}
         
-        post = self.client.post(path, prof, content_type="application/json", Authorization=self.auth,  X_Experience_API_Version="1.0.0")
+        post = self.client.post(path, json.dumps(prof), content_type="application/json", Authorization=self.auth,  X_Experience_API_Version="1.0.0")
         self.assertEqual(post.status_code, 204)
         
         get = self.client.get(path, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
         self.assertEqual(get.status_code, 200)
-        self.assertEqual(ast.literal_eval(get.content), prof)
+        self.assertEqual(json.loads(get.content), prof)
         self.assertEqual(get.get('etag'), '"%s"' % hashlib.sha1(get.content).hexdigest())
 
         params = {"profileId": "prof:test_post_and_put_profile", "agent": self.testagent}
@@ -390,12 +390,12 @@ class AgentProfileTests(TestCase):
         prof = {"wipe":"new data"}
         thehash = get.get('etag')
         
-        put = self.client.put(path, prof, content_type="application/json", If_Match=thehash, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
+        put = self.client.put(path, json.dumps(prof), content_type="application/json", If_Match=thehash, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
         self.assertEqual(put.status_code, 204)
         
         get = self.client.get(path, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
         self.assertEqual(get.status_code, 200)
-        self.assertEqual(ast.literal_eval(get.content), prof)
+        self.assertEqual(json.loads(get.content), prof)
         etag = '"%s"' % hashlib.sha1(get.content).hexdigest()
         self.assertEqual(get.get('etag'), etag)
 
@@ -403,15 +403,15 @@ class AgentProfileTests(TestCase):
         path = '%s?%s' % (reverse(views.agent_profile), urllib.urlencode(params))
         prof = {"test":"post updated profile","obj":{"agent":"mailto:test@example.com", "new":"thing"}, "added":"yes"}
         
-        post = self.client.post(path, prof, content_type="application/json", Authorization=self.auth,  X_Experience_API_Version="1.0.0")
+        post = self.client.post(path, json.dumps(prof), content_type="application/json", Authorization=self.auth,  X_Experience_API_Version="1.0.0")
         self.assertEqual(post.status_code, 409)
 
-        post = self.client.post(path, prof, content_type="application/json", If_Match=etag, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
+        post = self.client.post(path, json.dumps(prof), content_type="application/json", If_Match=etag, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
         self.assertEqual(post.status_code, 204)
 
         get = self.client.get(path, Authorization=self.auth,  X_Experience_API_Version="1.0.0")
         self.assertEqual(get.status_code, 200)
-        ret_json = ast.literal_eval(get.content)
+        ret_json = json.loads(get.content)
         self.assertEqual(ret_json['wipe'], "new data")
         self.assertEqual(ret_json['added'], prof['added'])
         self.assertEqual(ret_json['test'], prof['test'])
['lrs/objects/ActivityStateManager.py', 'lrs/objects/AgentManager.py', 'lrs/tests/AgentProfileTests.py', 'lrs/tests/ActivityProfileTests.py', 'lrs/objects/ActivityProfileManager.py']