fish2018/pansou · error

JSON解析失败

Error message

JSON解析失败: %w

What it means

fetchSearchResults unmarshals the response body into []CygPost; if the body is not valid JSON or does not match the expected array shape, this error wraps the json.Unmarshal failure. Typically the server returned HTML (error page/login page) instead of the REST JSON array.

Solutions

  1. Log the first ~500 bytes of the body on failure to see whether it's HTML, a JSON object, or truncated JSON.
  2. Handle WordPress REST error objects: try unmarshalling into a struct with code/message fields and surface that message.
  3. Use a browser-like User-Agent and cookies so the server returns real JSON instead of a challenge page.
  4. Validate the Content-Type header is application/json before unmarshalling.

Example fix

// before
var posts []CygPost
if err := json.Unmarshal(body, &posts); err != nil {
    return nil, fmt.Errorf("JSON解析失败: %w", err)
}
// after
var posts []CygPost
if err := json.Unmarshal(body, &posts); err != nil {
    return nil, fmt.Errorf("JSON解析失败: %w (body head: %.200s)", err, string(body))
}
Defensive patterns

Strategy: type-guard

Validate before calling

resp, _ := http.Get(searchURL)
ct := resp.Header.Get("Content-Type")
if !strings.Contains(ct, "application/json") {
    // upstream returned HTML/other: don't attempt JSON parse
}

Try / catch

results, err := plugin.SearchWithResult(ctx, opts)
if err != nil && strings.Contains(err.Error(), "JSON解析失败") {
    // response was not the expected JSON array: log body, try alternate source
}

Prevention

When it happens

Trigger: searchImpl gets a 200 whose body is not a JSON array of CygPost — e.g. an HTML block/interstitial page, a WordPress JSON error object ({"code":...}) instead of an array, or truncated/malformed JSON.

Common situations: WAF or anti-bot serves a 200 HTML challenge page; REST API returns an error object with 200 in some plugin setups; content-type/encoding mismatch; upstream changed response schema.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/a719d330c8f75525. Report an issue: GitHub.

Appendix: source

Thrown at plugin/cyg/cyg.go:166

	if err != nil {
		return nil, fmt.Errorf("HTTP请求失败: %w", err)
	}
	defer resp.Body.Close()

	// 检查状态码
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("HTTP错误状态码: %d", resp.StatusCode)
	}

	// 解析响应
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取响应失败: %w", err)
	}

	var posts []CygPost
	if err := json.Unmarshal(body, &posts); err != nil {
		return nil, fmt.Errorf("JSON解析失败: %w", err)
	}

	return posts, nil
}

// fetchDownloadLinksAsync 并发获取下载链接
func (p *CygPlugin) fetchDownloadLinksAsync(client *http.Client, posts []CygPost, keyword string) []model.SearchResult {
	var wg sync.WaitGroup
	resultChan := make(chan model.SearchResult, len(posts))

	// 限制并发数量
	semaphore := make(chan struct{}, 10) // 最多10个并发

	for _, post := range posts {
		wg.Add(1)
		go func(p *CygPlugin, post CygPost) {
			defer wg.Done()

View on GitHub (pinned to beaa561337)