function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
buggs sfdcbuggs sfdc 

System.JSONException: Unexpected character ('S' (code 83)): expected a valid value (number, String, array, object, 'true', 'false' or 'null') at input location [1,2]

HI,

Can any one help me out in covering the test code for below batch class, so far i covered 55% but am getting an error.Here am attching my test class even,please check and suggest me how to resolve it.
@istest
public class FieldsValidator_test {
public static String CRON_EXP = '0 0 0 15 3 ? 2022';
  static testMethod void FVtest(){
   
   Test.startTest();
       List< ObjectsExistingFieldsInfo__c> objex = new List<ObjectsExistingFieldsInfo__c>();
       
        ObjectsExistingFieldsInfo__c obj1 = new ObjectsExistingFieldsInfo__c();
        obj1.Object_API_Name__c = 'Account';
        obj1.Fields_Count__c = 1.9666;
        obj1.Fields_Info__c = 'SICCode__c';
        obj1.CurrencyIsoCode = 'AUD';
        objex.add(obj1);
        
        ObjectsExistingFieldsInfo__c obj2 = new ObjectsExistingFieldsInfo__c();
        obj2.Object_API_Name__c = 'Contact';
        obj2.Fields_Count__c = 1.9666;
        obj2.Fields_Info__c = 'SICCode__c';
       obj2.CurrencyIsoCode ='AUD';
        objex.add(obj2);
        
        ObjectsExistingFieldsInfo__c obj3 = new ObjectsExistingFieldsInfo__c();
        obj3.Object_API_Name__c = 'Opportunity';
        obj3.Fields_Count__c = 1.9666;
        obj3.Fields_Info__c = '';
       obj3.CurrencyIsoCode ='AUD';
        objex.add(obj3);
        
        ObjectsExistingFieldsInfo__c obj4 = new ObjectsExistingFieldsInfo__c();
        obj4.Object_API_Name__c = 'Lead';
        obj4.Fields_Count__c = 1.9666;
        obj4.Fields_Info__c = 'SICCode__c';
       obj4.CurrencyIsoCode ='AUD';
        objex.add(obj4);
        
        ObjectsExistingFieldsInfo__c obj5 = new ObjectsExistingFieldsInfo__c();
        obj5.Object_API_Name__c = 'CampaignMember';
        obj5.Fields_Count__c = 1.9666;
        obj5.Fields_Info__c = 'SICCode__c';
        obj5.CurrencyIsoCode ='AUD';
        objex.add(obj5);
        
        ObjectsExistingFieldsInfo__c obj6 = new ObjectsExistingFieldsInfo__c();
        obj6.Object_API_Name__c = 'zqu__Quote__c';
        obj6.Fields_Count__c = 1.9666;
        obj6.Fields_Info__c = 'SICCode__c';
        obj6.CurrencyIsoCode ='AUD';
        objex.add(obj6);

         Insert objex;
         

      FieldsValidator obj = new FieldsValidator ();
      DataBase.executeBatch(obj);
       Test.stopTest();

   }
}


Any help greatly appreciated.

Thanks in Advance
global class FieldsValidator implements Database.Batchable<Sobject> {
    global Database.queryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator('select name, fields_info__c, fields_count__c from ObjectsExistingFieldsInfo__c');
    }
    global void execute(Database.BatchableContext bc, List<SObject> sobjLst) {
        String[] types = new String[]{'Account','Contact'};
        String emailBody = '';
        // Make the describe call
        Schema.DescribeSobjectResult[] results = Schema.describeSObjects(types);
        Map<String,List<Field>> objFieldsDesMap = new Map<String,List<Field>>();
        // For each returned result, get some info
        for(Schema.DescribeSobjectResult res : results) {
            Map<String, Schema.SObjectField> objectFields = res.fields.getMap();
            for(Schema.SObjectField fDes : objectFields.values()) {
                if(fDes.getDescribe().isCustom()) {
                    system.debug(fDes.getDescribe().getName()+'@@@'+fDes.getDescribe().getType());
                    String fieldAPIName = String.valueOf(fDes.getDescribe().getName());
                    String fieldDataType = String.valueOf(fDes.getDescribe().getType());
                    if(objFieldsDesMap.containsKey(res.getName())) {
                        objFieldsDesMap.get(res.getName()).add(new Field(fieldAPIName,fieldDataType));
                    }
                    else {
                        objFieldsDesMap.put(res.getName(),new List<Field>{new Field(fieldAPIName,fieldDataType)});
                    }
                }       
            }
        }
        Map<String, ObjectsExistingFieldsInfo__c> objectInfoMap = new Map<String, ObjectsExistingFieldsInfo__c>();
        for(ObjectsExistingFieldsInfo__c objInfo : [select Field_API_Name__c , Fields_Count__c, Fields_Info__c from 
        ObjectsExistingFieldsInfo__c where Field_API_Name__c in: types]) {
            objectInfoMap.put(objInfo.Field_API_Name__c,objInfo);
        }
        for(String type : types) {
            if(objectInfoMap.get(type).fields_count__c == null) {
                objectInfoMap.get(type).fields_count__c = objFieldsDesMap.get(type).size();
                objectInfoMap.get(type).fields_info__c = JSON.serialize(objFieldsDesMap.get(type));
            }       
            else {
                System.debug('entering to else condition...');
                System.debug('entering to for loop..');
                List<Field> exstingFields = new List<Field>();
                List<Field> newFields = new List<Field>();
                Map<String,Field> bkupexstingFields = new Map<String,Field>();
                Map<String,Field> bkupnewFields = new Map<String,Field>();
                exstingFields = (List<Field>)JSON.deserialize(objectInfoMap.get(type).fields_info__c, List<Field>.class);
                System.debug('exstingFields: '+exstingFields);
                newFields.addAll(objFieldsDesMap.get(type));
                System.debug('objFieldsDesMap: '+objFieldsDesMap);
                System.debug('newFields: '+newFields);
                for(Field f : exstingFields) {
                    bkupexstingFields.put(f.apiName,f);
                }
                for(Field f : newFields) {
                    bkupnewFields.put(f.apiName,f);
                }
                for(Field f : exstingFields) {
                    bkupnewFields.remove(f.apiName);
                }
                for(Field f : newFields) {
                    bkupexstingFields.remove(f.apiName);
                }
                System.debug(bkupnewFields+'@@@'+bkupexstingFields);
                emailBody += type + ' : ';
                //for new fields
                for(Field f :bkupnewFields.values()) {
                    emailBody += f.apiName + ' with datatype '+f.dataType+' is newly created.'; 
                }
                objectInfoMap.get(type).fields_count__c = objFieldsDesMap.get(type).size();
                objectInfoMap.get(type).fields_info__c = JSON.serialize(objFieldsDesMap.get(type));
            }
        }
        /*** Sending Email ***/
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.setToAddresses(new List<String>{system.label.Dev_Admin});
        mail.setSubject('Fields Update');
        mail.setPlainTextBody(emailBody);
        update objectInfoMap.values();
        Messaging.sendEmail(new Messaging.SingleEmailMessage[]{mail});
    }
    global void finish(Database.BatchableContext bc) {
    } 
    public class Field {
        String apiName, dataType;
        public Field(String apiName, String dataType) {
            this.apiName = apiName;
            this.dataType = dataType;
        }
    }
}
Vincent Ip 7Vincent Ip 7
From my reading it looks like  you have possibly a problem on line 45
 
exstingFields = (List<Field>)JSON.deserialize(objectInfoMap.get(type).fields_info__c, List<Field>.class);

if i'm reading this right, the parameter "objectInfoMap.get(type).fields_info__c" has the value "SICCode__c" (as it was set in your test class) and that is not going to deserialize into a List<Field> object.
 
buggs sfdcbuggs sfdc
HI  Vincent Ip 7,

Can you provide me any solution to cover the rest if the code.

Thanks a tonn for quick reply!
Vincent Ip 7Vincent Ip 7
well, fix your bug first, doing that will raise your code coverage.  

Once that is done, you can figure out which paths are not being run and tackle that next.