2

I write an API using springMVC.It's a simple API, I just use it to test JsonProvider.

@ResponseBody
@RequestMapping(value = "/api/test", method = RequestMethod.GET)
public TestClass test(final HttpServletRequest request,
        final HttpServletResponse response){
    return new TestClass("cc");
}

class TestClass{

    public TestClass(){

    }
    public TestClass(final String name) {
        super();
        this.name = name;
    }

    private String name;

    public String getName() {
        return name;
    }

    public void setName(final String name) {
        this.name = name;
    }

}

The API simply returns enter image description here
But JsonProvider just throws a compile error.

    Severity    Code    Description Project File    Line
    Error       The type provider 'ProviderImplementation.JsonProvider' reported an error: Cannot read sample JSON from 'http://localhost/api/test': Invalid JSON starting at character 0, snippet = 
    ----
    "{\"name\":
    -----
    json = 
    ------
    "{\"name\":\"cc\"}"
    ------- JsonProcess c:\users\xx\documents\visual studio 2015\Projects\JsonProcess\JsonProcess\Program.fs    8

The F# code:

    open FSharp.Data

    [<Literal>]
    let jsonValue = """
    {"name":"cc"}
    """

    type JsonData = JsonProvider<"http://localhost/api/test">

    [<EntryPoint>]
    let main argv = 
        0 // return an integer exit code

Use the String literal jsonValue as sample is ok.type JsonData = JsonProvider<jsonValue>

ildjarn
  • 62,044
  • 9
  • 127
  • 211
fairjm
  • 1,115
  • 12
  • 26
  • 3
    Looks like some text encoding problem. Have you tried fiddlin with the `Culture` and `Encoding` parameters of the `JsonProvider` type? I would also opening your JSON file from Notepad++ or a similar tool, with hidden characters enabled, and comparing it to a known working JSON (e.g. http://api.worldbank.org/country/cz/indicator/GC.DOD.TOTL.GD.ZS?format=json) – piaste Oct 08 '15 at 08:54
  • @piaste I try to add `Encoding = "UTF-8"` but still no help.Maybe I should try `Culture` later.But as you can see the chrome plugin works fine.It formats the JSON correctly and java json lib likes `jackson` also works.I try to use other APIs like worldbank and taobao, they are ok.It's strange. – fairjm Oct 08 '15 at 13:47
  • Try using Fiddler (http://www.telerik.com/fiddler) to access both your API and the WorldBank API. You can use the "TextView" and especially the "HexView" tabs to figure out any possible differences. – piaste Oct 08 '15 at 14:04
  • Can [it](http://stackoverflow.com/questions/10323957/posting-json-to-rest-api/10363876#10363876) help you? Probably the same problem as you. – knagaev Oct 09 '15 at 08:29
  • @knagaev Still compilation error.But other utils work fine(`jackson` for java,`JSON.NET ` for .NET,chrome json plugin and so on) – fairjm Oct 09 '15 at 09:30

1 Answers1

2

I checked the FSharp.Data source code (its the function asyncRead) to see how they download the JSON. It basically boils down to this:

let readString =
  async {
    let contentTypes  = [ HttpContentTypes.Json ]
    let headers       = [ 
                          HttpRequestHeaders.UserAgent ("F# Data JSON Type Provider") 
                          HttpRequestHeaders.Accept (String.concat ", " contentTypes) 
                        ]
    let! text     = Http.AsyncRequestString("http://www.kujiale.com/api/askinvitesearch?query=cc", headers = headers) 

    return text
  }

If one runs this code against the url http://www.kujiale.com/api/askinvitesearch?query=cc we see something interesting about what's returned:

"[{\"linkToIdeaBook\":\"/u/3FO4K4UR89F1/huabao\",\"linkToDesi

Note that the content starts with " and that the "strings" are "escaped" with \. So it seems the JSON document is returned as an escaped string. According to json.org the root object must be either an object or array so the parser fails at character 0.

If one switches to contentType HttpContentTypes.Text it starts like this:

[{"linkToIdeaBook":"/u/3FO4K4UR89F1/huabao","linkToDesignCollect":"/u

Which actually turns out to be a valid JSON object.

To me it seems somewhat odd that if you ask for content with content type JSON you get an escaped string but that seems to be the root cause of the failure.

How to resolve it is more difficult to say. One way forward would be a PR to FSharp.Data to allow users to specify the content type used to download content.

  • 1
    Thx a lot.I changed the return type in springMVC to `application/json` it returns string with `"`. – fairjm Oct 11 '15 at 09:20