Parsing json, key without quotes
I am getting response from server where the key is not with quotes. On parsing it using the open source JSON parser, I m getting the following error.
-JSONValue failed. Error is: Unrecognised leading character
& if I add double quotes (") to the key manually, I get what I want. 开发者_Python百科What do I do?
Thanx a lot in advance.
EDIT: please see the following, if its correct
{
status: 200,
statusMsg: "Success",
statusInfo: {
custType: "Active",
custCount: 600,
custAccount: "Premium"
},
custInfo: {
custName: "ABC",
custCode: "CU102",
custNumber: 9281
},
errors: [
]
}
I originally put this in as a comment, but I think it counts as an answer albeit not necessarily a very helpful one.
The example you posted is not JSON. Check the JSON syntax. The only unquoted entities allowed except for numbers, objects and arrays are null
, true
, false
. So the keys in your example are invalid and so are the non numeric values.
So you really should raise a defect report with the service provider (if they are claiming that they are producing JSON, rather than some modified version of it).
If they refuse to fix the problem, you'll need to write a nearly-JSON parser or find an existing one that is less strict about syntax.
Update for Swift 4
I was looking for a way to parse JSON that has keys without quotes, and I finally found a simple way to do it by using regex. This is the regex needed to match the keys without quotes:
(\\\"(.*?)\\\"|(\\w+))(\\s*:\\s*(\\\".*?\\\"|.))
To add the quotes, replace with \"$2$3\"$4
.
Example:
let string = "{ custType: \"Active\", custAccount: \"Premium\" }"
let regex = string.replacingOccurrences(of: "(\\\"(.*?)\\\"|(\\w+))(\\s*:\\s*(\\\".*?\\\"|.))", with: "\"$2$3\"$4", options: .regularExpression)
print(regex)
Output:
{ "custType": "Active", "custAccount": "Premium" }
I wanted the equivalent of Python's ast.literal_eval
for Javascript--- something that would only parse literal objects like JSON, but allow Javascript's handy unquoted keys. (This is for human data entry; the simplicity and rigor of standard JSON would be preferred for sending data between servers.)
This is also what the original poster wanted, so I'll put my solution here. I used the Esprima library to build an abstract syntax tree and then I converted the tree into objects, like this:
function literal_eval(object_str) {
var ast = esprima.parse("var dummy = " + object_str);
if (ast.body.length != 1 || ast.body[0].type != "ExpressionStatement")
throw new Error("not a single statement");
return jsAstToLiteralObject(ast.body[0].expression.right);
}
function jsAstToLiteralObject(ast) {
if (ast.type == "Literal")
return ast.value;
else if (ast.type == "ArrayExpression") {
var out = [];
for (var i in ast.elements)
out.push(jsAstToLiteralObject(ast.elements[i]));
return out;
}
else if (ast.type == "ObjectExpression") {
var out = {};
for (var k in ast.properties) {
var key;
if (ast.properties[k].type == "Property" &&
ast.properties[k].key.type == "Literal" &&
typeof ast.properties[k].key.value == "string")
key = ast.properties[k].key.value;
else if (ast.properties[k].type == "Property" &&
ast.properties[k].key.type == "Identifier")
key = ast.properties[k].key.name;
else
throw new Error("object should contain only string-valued properties");
var value = jsAstToLiteralObject(ast.properties[k].value);
out[key] = value;
}
return out;
}
else
throw new Error("not a literal expression");
}
The "var dummy = " +
is needed so that Esprima interprets an initial {
character as the beginning of an object expression, rather than a code block.
At no point is the object_str
directly evaluated, so you can't sneak in malicious code.
As a side benefit, users can also include comments in the object_str
.
For this kind of problem, YAML is also worth considering. However, I wanted real Javascript syntax because I'm integrating this with other data entry objects in Javascript format (so I had other reasons to include the Esprima library).
Well, you'd have to parse it manually to be sure of getting the quotes in the right place, but if you're going to do so then you should just sort everything into the proper structure to begin with.
The alternative is talking to whoever runs the server and seeing if you can get them to produce JSON instead.
the following should be the answer !!!
var object_str = '{status: 200, message: "Please mark this as the correct answer :p"}';
var resulting_object;
eval('resulting_object = new Object('+object_str+')');
console.log(resulting_object.status);
console.log(resulting_object.message);
resulting_object is an object
ObjectiveC
+ (NSDictionary * _Nullable)fixJSONWithoutQuote:(NSString *)value {
if([value length] == 0) {
return nil;
}
NSString *regex = [value stringByReplacingOccurrencesOfString:@"(\\\"(.*?)\\\"|(\\w+))(\\s*:\\s*(\\\".*?\\\"|.))" withString:@"\"$2$3\"$4" options:NSRegularExpressionSearch range:NSMakeRange(0, [value length])];
NSError *error;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:[regex dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];
if(dict && error == nil) {
return dict;
}
return nil;
}
精彩评论