facebook-java-business-sdk icon indicating copy to clipboard operation
facebook-java-business-sdk copied to clipboard

com.facebook.ads.sdk.APIException$MalformedResponseException: Invalid response string

Open JohnNguyenTR opened this issue 3 years ago • 4 comments

Which SDK version are you using?

I'm upgrading my FB Extract API app from FB Java business sdk v11 to v12.0.1

I run a test to extract all Adset field for an account using the Adset.java

What's the issue?

I got the error: com.facebook.ads.sdk.APIException$MalformedResponseException: Invalid response string ....

at com.facebook.ads.sdk.AdSet.parseResponse(AdSet.java:348) at com.facebook.ads.sdk.AdSet$APIRequestGet.parseResponse(AdSet.java:5124) at com.facebook.ads.sdk.AdSet$APIRequestGet.execute(AdSet.java:5135) at com.facebook.ads.sdk.AdSet$APIRequestGet.execute(AdSet.java:5129) at com.facebook.ads.sdk.AdSet.fetchById(AdSet.java:193)

Steps/Sample code to reproduce the issue

public String getAdSetData(String adSetId, APIContext context) throws APIException {

    try {

           AdSet apiResponse = AdSet.fetchById((String) adSetId, context);
        // AdSet apiResponse = AdSet.fetchByIds( .....)
        if (apiResponse == null) {
            return "null";
        }
        GsonBuilder builder = new GsonBuilder();
        Gson gson = builder.create();
        JsonObject jsonObject = apiResponse.getRawResponseAsJsonObject();

        LinkedTreeMap dataMap = gson.fromJson(jsonObject, LinkedTreeMap.class);

        if (apiResponse.getFieldTargeting() != null) {
                String targetingString = apiResponse.getFieldTargeting().toString();
            JsonObject targeting = gson.fromJson(targetingString, JsonObject.class);
            parseAdSetTargeting(dataMap, targeting);

        }

        return gson.toJson(dataMap);

    } catch (Exception e) {
        e.printStackTrace();
        log.error("Exception in getAdSetData(): " + e.getMessage());
        throw e;
    }

    //return null;
}

def "Should get Ad Account Campaign Adsets Data"() { when: def adAcctCampaigns = facebookService.getAdSetData("23842996206500470", context) println adAcctCampaigns then: adAcctCampaigns != null }

Observed Results:

  • What happened? This could be a description, log output, etc. com.facebook.ads.sdk.APIException$MalformedResponseException: Invalid response string: {"account_id":"678148202394074","attribution_spec":[{"event_type":"CLICK_THROUGH","window_days":1}],"bid_strategy":"LOWEST_COST_WITHOUT_CAP","billing_event":"LINK_CLICKS","budget_remaining":"0","campaign":{"id":"23842996206370470"},"campaign_id":"23842996206370470","configured_status":"ACTIVE","created_time":"2018-08-13T16:22:03-0400","daily_budget":"0","destination_type":"UNDEFINED","effective_status":"ACTIVE","end_time":"2018-08-16T23:09:32-0400","id":"23842996206500470","is_dynamic_creative":false,"lifetime_budget":"2500","lifetime_imps":0,"multi_optimization_goal_weight":"UNDEFINED","name":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ,,,,,,,,,,,,,,,,,,

    at com.facebook.ads.sdk.AdSet.parseResponse(AdSet.java:348) at com.facebook.ads.sdk.AdSet$APIRequestGet.parseResponse(AdSet.java:5124) at com.facebook.ads.sdk.AdSet$APIRequestGet.execute(AdSet.java:5135) at com.facebook.ads.sdk.AdSet$APIRequestGet.execute(AdSet.java:5129) at com.facebook.ads.sdk.AdSet.fetchById(AdSet.java:193) at com.findlaw.facebook.ads.service.impl.FacebookServiceImpl.getAdSetData(FacebookServiceImpl.java:619) at com.findlaw.facebook.ads.service.impl.FacebookServiceImplFunctionalTest.Should get Ad Account Campaign Adsets Data(FacebookServiceImplFunctionalTest.groovy:134) Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2294 path $.targeting_optimization_types[0] at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220) at com.google.gson.Gson.fromJson(Gson.java:879) at com.google.gson.Gson.fromJson(Gson.java:844) at com.google.gson.Gson.fromJson(Gson.java:793) at com.google.gson.Gson.fromJson(Gson.java:765) at com.facebook.ads.sdk.AdSet.loadJSON(AdSet.java:228) at com.facebook.ads.sdk.AdSet.parseResponse(AdSet.java:341) ... 6 more Caused by: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2294 path $.targeting_optimization_types[0] at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350) at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:172) at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:116) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:216) ... 12 more

Expected Results:

  • What did you expect to have? I expected no error. Please note that if I replace only the Adset.java version 12.0.1 by version 11 then my run doesn't have any error. Please advise.

JohnNguyenTR avatar Jan 31 '22 19:01 JohnNguyenTR

Comparing Adset.java version 11 and 12.0.1, I notice that there are two additional fields in the Adset.java version 12.0.1: "existing_customer_budget_percentage" and "targeting_optimization_types". My error appears to be related with the new filed " "targeting_optimization_types". Does anyone have issue with that new field "targeting_optimization_types"?

JohnNguyenTR avatar Jan 31 '22 19:01 JohnNguyenTR

Just a note: If I comment the new field in both places of the public static final String[] FIELDS = {" ...., then that error is gone. However, the returned json does not contain that targeting_optimization_types anymore. Do you have any better way to deal with that "targeting_optimization_types" new field?

JohnNguyenTR avatar Jan 31 '22 20:01 JohnNguyenTR

I've got the same issue. I had to remove from request both of those new fields to make it work (existing_customer_budget_percentage,targeting_optimization_types).

vp-cs avatar Feb 23 '22 14:02 vp-cs

We are aware of this issue. The root cause is that the type targeting_optimization_types is no longer map<string, int> but list<map<string, int>>. We are working on a fix but right now here is a patch:

diff --git a/sdk/servers/java/release/src/main/java/com/facebook/ads/sdk/AdSet.java b/sdk/servers/java/release/src/main/java/com/facebook/ads/sdk/AdSet.java
index e0a767f2..162cf60c 100644
--- a/sdk/servers/java/release/src/main/java/com/facebook/ads/sdk/AdSet.java
+++ b/sdk/servers/java/release/src/main/java/com/facebook/ads/sdk/AdSet.java
@@ -158,7 +158,7 @@ public class AdSet extends APINode {
   @SerializedName("targeting")
   private Targeting mTargeting = null;
   @SerializedName("targeting_optimization_types")
-  private Map<String, Long> mTargetingOptimizationTypes = null;
+  private List<Map<String, Long>> mTargetingOptimizationTypes = null;
   @SerializedName("time_based_ad_rotation_id_blocks")
   private List<List<Long>> mTimeBasedAdRotationIdBlocks = null;
   @SerializedName("time_based_ad_rotation_intervals")
@@ -975,11 +975,11 @@ public class AdSet extends APINode {
     this.mTargeting = Targeting.getGson().fromJson(value, type);
     return this;
   }
-  public Map<String, Long> getFieldTargetingOptimizationTypes() {
+  public List<Map<String, Long>> getFieldTargetingOptimizationTypes() {
     return mTargetingOptimizationTypes;
   }
 
-  public AdSet setFieldTargetingOptimizationTypes(Map<String, Long> value) {
+  public AdSet setFieldTargetingOptimizationTypes(List<Map<String, Long>> value) {
     this.mTargetingOptimizationTypes = value;
     return this;
   }

stcheng avatar Apr 12 '23 00:04 stcheng