Salesforce JSON解析

前言


JSON(JavaScript Object Notation)格式是目前比较流行的一种数据传输方式。JSON是一种轻量级的数据传输方式(尤其相对于XML方式),而且采用JSON传输数据结构清晰,易于理解和解析。在Salesforce中大部分的数据传输都可以采用JSON(SOAP/Metadata部分强制需要XML),所以有必要去了解Salesforce对于JSON的支持力度。

相关类

  1. JSONParser:需要实例,以调用相应的方法。主要功能是将JSON字符串转化为对象,并提供可读取为Apex基本类型/Apex Object方法,例如:getDateValue();
  2. JSONGenerator:需要实例,以调用相应的方法。主要功能是将Apex对象等转化为JSON字符串,提供Step By Step写入,例如:writeTimeField();
  3. JSON:静态方法,不需要实例。一个强大的Super(效果相当于,并不是技术实现),提供了JSONParser/JSONGenerator实例方法。并提供将Apex对象转为JSON字符串/JSON字符串转为Apex Object/Collection(List/Map等);
  4. JSONToken:枚举类型。主要服务于JSONParser
下面是一段JSON数据,我们尝试用不同的方式解析/组装:
{
    "messages": [
        {
            "type": "Availability",
            "message": {
                "results": [
                    {
                        "id": "5732800000005GQ",
                        "isAvailable": true
                    }
                ]
            }
        }
    ]
}

解析


以获得results中isAvailable值为例:

  1. JSONParser
    String jsonS = '{"messages":[{"type":"Availability","message":{"results":[{"id":"5732800000005GQ","isAvailable":true}]}}]}';
    
    JSONParser parser = JSON.createParser(jsonS);
    while (parser.nextToken() != null) {
    
    	if(parser.getCurrentToken() == JSONToken.FIELD_NAME && 
    			parser.getText() == 'isAvailable') {
    		parser.nextValue();
    		System.debug('-- isAvailable: ' + parser.getBooleanValue());
    	}
    
    }
  2. JSON
    String jsonS = '{"messages":[{"type":"Availability","message":{"results":[{"id":"5732800000005GQ","isAvailable":true}]}}]}';
    
    Map obj = (Map)JSON.deserializeUntyped(jsonS);
    List messages = (List)obj.get('messages');
    for(Object o : messages) {
    
    	Map messageO = (Map)o;
    	Map message = (Map)messageO.get('message');
    	List results = (List)message.get('results');
    
    	for(Object r : results) {
    
    		Map result = (Map)r;
    		System.debug('-- isAvailable: ' + result.get('isAvailable'));
    
    	}	
    
    } 
        
       

    以上代码是一种简单的解析,不涉及直接解析为Class。直观的比较而言似乎JSONParser解析要比JSON更简单、方便一些,JSON的解析方式涉及到的类型转化很多、很繁琐,一不小心就得不到想要的结果。实际上JSONParser的解析方式如果我们想要直接得到某个属性而不考虑其他,确实很快很便捷。但是却受到两个重要的限制:

    1. Key是否有重复(在JSON对象中我们很容易在不同的层级中设置相同的Key),若是这样我们可能得到错误的值;
    2. 没有层级结构:解析的结果我们无法完全的获悉层次结构。
    它的优势也很明显,可以直接获取到属性值并且获得相应的类型(除String,获取String要使用getBlobValue())。JSON的解析方式看起来确实复杂而且实际执行也较为复杂,但却有个优势就是可以获得层级结构,并轻松的转为相应的Map(前提是解析过程已有)。

    序列化


    我们同样以构造出上述的结构为例:
    1. JSONGenerator
      JSONGenerator generator = JSON.createGenerator(true);
      generator.writeStartObject();
      	generator.writeFieldName('messages');
      	generator.writeStartArray();
      		generator.writeStartObject();
      			generator.writeObjectField('type', 'Availability');
      			generator.writeFieldName('message');
      			generator.writeStartObject();
      				generator.writeFieldName('results');
      				generator.writeStartArray();
      					generator.writeStartObject();
      					generator.writeObjectField('id', '5732800000005GQ');
      					generator.writeObjectField('isAvailable', true);
      					generator.writeEndObject();
      				generator.writeEndArray();
      			generator.writeEndObject();
      		generator.writeEndObject();
      	generator.writeEndArray();
      generator.writeEndObject();
      
      System.debug(generator.getAsString());

    2. JSON
      Map result = new Map();
      result.put('id', '5732800000005GQ');
      result.put('isAvailable', true);
      List> results = new List>();
      results.add(result);
      Map message = new Map();
      message.put('type', 'Availability');
      message.put('message', results);
      List messagesL = new List();
      messagesL.add(message);
      Map messages = new Map();
      messages.put('messages', messagesL);
      
      System.debug(JSON.serializePretty(messages)); 
           
          
         

      以上代码简单的构建了一个JSON字符串。通过代码可以看到JSONGenerator构建方式是由上之下,一级一级搭建层级结构,整个过程可控但稍显臃肿;JSON的方式是先构建相应的对象(这里由Map/List实现),在转化为JSON字符串,层级结构由对象结构决定(由于Map无序,不保证同级顺序),转化方式较为简洁。以上方式不涉及直接转化Object,只涉及基本字段和Array。


      心得


      1. JSON的解析和转化在Salesforce内相对而言较为简单,根据需求不同提供不同的解决方式(过程时候可控);
      2. 在涉及到解析较为严谨的地方(例如接口数据等)建议转化为对应的Object,而不是Map;
      3. JSON中带有Pretty的方法是输出是否缩进;
      4. 在实际过程中,笔者较多的使用JOSN Class的解析和转化方式,解析直接,转化方便;
      5. JSON解析为Object的情况下:两种解析方式均提供了带有Strict方法(是否严格匹配)。

      附录


      各自的方法和属性:
      • JSON
        • createGenerator(prettyPrint): Returns a new JSON generator;
        • createParser(jsonString): Returns a new JSON parser;
        • deserialize(jsonString, apexType): Deserializes the specified JSON string into an Apex object of the specified type;
        • deserializeStrict(jsonString, apexType): Deserializes the specified JSON string into an Apex object of the specified type;
        • deserializeUntyped(jsonString): Deserializes the specified JSON string into collections of primitive data types;
        • serialize(objectToSerialize): Serializes Apex objects into JSON content;
        • serializePretty(objectToSerialize): Serializes Apex objects into JSON content and generates indented content using the pretty-print format.
      • JSONGenerator
        • close(): Closes the JSON generator;
        • getAsString()Returns the generated JSON content.
        • isClosed()Returns true if the JSON generator is closed; otherwise, returns false.
        • writeBlob(blobValue)Writes the specified Blob value as a base64-encoded string.
        • writeBlobField(fieldName, blobValue)Writes a field name and value pair using the specified field name and BLOB value.
        • writeBoolean(blobValue)Writes the specified Boolean value.
        • writeBooleanField(fieldName, booleanValue)Writes a field name and value pair using the specified field name and Boolean value.
        • writeDate(dateValue)Writes the specified date value in the ISO-8601 format.
        • writeDateField(fieldName, dateValue)Writes a field name and value pair using the specified field name and date value. The date value is written in the ISO-8601 format.
        • writeDateTime(datetimeValue)Writes the specified date and time value in the ISO-8601 format.
        • writeDateTimeField(fieldName, datetimeValue)Writes a field name and value pair using the specified field name and date and time value. The date and time value is written in theISO-8601 format.
        • writeEndArray()Writes the ending marker of a JSON array (']').writeEndObject()Writes the ending marker of a JSON object ('}').
        • writeFieldName(fieldName)Writes a field name.writeId(identifier)Writes the specified ID value.
        • writeIdField(fieldName, identifier)Writes a field name and value pair using the specified field name and identifier value.
        • writeNull()Writes the JSON null literal value.
        • writeNullField(fieldName)Writes a field name and value pair using the specified field name and the JSON null literal value.
        • writeNumber(number)Writes the specified decimal value.writeNumber(number)Writes the specified double value.
        • writeNumber(number)Writes the specified integer value.writeNumber(number)Writes the specified long value.
        • writeNumberField(fieldName, number)Writes a field name and value pair using the specified field name and decimal value.
        • writeNumberField(fieldName, number)Writes a field name and value pair using the specified field name and double value.
        • writeNumberField(fieldName, number)Writes a field name and value pair using the specified field name and integer value.
        • writeNumberField(fieldName, number)Writes a field name and value pair using the specified field name and long value.
        • writeObject(anyObject)Writes the specified Apex object in JSON format.
        • writeObjectField(fieldName, value)Writes a field name and value pair using the specified field name and Apex object.
        • writeStartArray()Writes the starting marker of a JSON array ('[').writeStartObject()Writes the starting marker of a JSON object ('{').
        • writeString(stringValue)Writes the specified string value.writeStringField(fieldName, stringValue)Writes a field name and value pair using the specified field name and string value.
        • writeTime(timeValue)Writes the specified time value in the ISO-8601 format.
        • writeTimeField(fieldName, timeValue)Writes a field name and value pair using the specified field name and time value in the ISO-8601 format.
      • JSONParser
        • clearCurrentToken()Removes the current token.
        • getBlobValue()Returns the current token as a BLOB value.
        • getBooleanValue()Returns the current token as a Boolean value.
        • getCurrentName()Returns the name associated with the current token.
        • getCurrentToken()Returns the token that the parser currently points to or null if there's no current token.
        • getDatetimeValue()Returns the current token as a date and time value.
        • getDateValue()Returns the current token as a date value.getDecimalValue()Returns the current token as a decimal value.
        • getDoubleValue()Returns the current token as a double value.getIdValue()Returns the current token as an ID value.
        • getIntegerValue()Returns the current token as an integer value.
        • getLastClearedToken()Returns the last token that was cleared by the clearCurrentToken method.
        • getLongValue()Returns the current token as a long value.
        • getText()Returns the textual representation of the current token or null if there's no current token.
        • getTimeValue()Returns the current token as a time value.
        • hasCurrentToken()Returns true if the parser currently points to a token; otherwise, returns false.
        • nextToken()Returns the next token or null if the parser has reached the end of the input stream.
        • nextValue()Returns the next token that is a value type or null if the parser has reached the end of the input stream.
        • readValueAs(apexType)Deserializes JSON content into an object of the specified Apex type and returns the deserialized object.
        • readValueAsStrict(apexType)Deserializes JSON content into an object of the specified Apex type and returns the deserialized object. All attributes in the JSONcontent must be present in the specified type.
        • skipChildren()Skips all child tokens of type JSONToken.START_ARRAY and JSONToken.START_OBJECT that the parser currentlypoints to.
      • JSONToken
        • END_ARRAY: The ending of an object value. This token is returned when '}' isencountered.
        • END_OBJECTFIELD_NAME: A string token that is a field name.
        • NOT_AVAILABLE:  The requested token isn't available.The start of an array value. This token is returned when '[' isencountered.
        • START_ARRAY: The start of an object value. This token is returned when '{' isencountered.
        • START_OBJECT: An embedded object that isn't accessible as a typical objectstructure that includes the start and end object tokens START_OBJECT and END_OBJECT but is represented as a raw object.
        • VALUE_EMBEDDED_OBJECTVALUE_FALSE: The literal “false” value.
        • VALUE_NULL:  The literal “null” value.
        • VALUE_NUMBER_FLOAT:  A float value.
        • VALUE_NUMBER_INT:  An integer value.1830Reference JSONToken EnumEnum Value Description
        • VALUE_STRING:  A string value.
        • VALUE_TRUE:  A value that corresponds to the “true” string literal.

      参考


      https://resources.docs.salesforce.com/208/latest/en-us/sfdc/pdf/salesforce_apex_language_reference.pdf

      你可能感兴趣的:(Salesforce)