code: func getJSONData(c context.Context, url string, expiration time.Duration, target interface{}) error {
  	// Try memcache first.
  	item := memcache.NewItem(c, "url:"+url)
  	if err := memcache.Get(c, item); err == nil {
  		if err = json.Unmarshal(item.Value(), target); err == nil {
  			return nil
  		}
  		logging.WithError(err).Warningf(c, "couldn't load stored item from datastore")
  	} else if err != memcache.ErrCacheMiss {
  		logging.WithError(err).Errorf(c, "memcache is having issues")
  	}
  
  	// Fetch it from the app.
  	transport := urlfetch.Get(c)
  	response, err := (&http.Client{Transport: transport}).Get(url)
  	if err != nil {
  		return errors.Annotate(err, "failed to get data from %q", url).Err()
  	}
  	defer response.Body.Close()
  
  	bytes, err := ioutil.ReadAll(response.Body)
  	if err != nil {
  		return errors.Annotate(err, "failed to read response body from %q", url).Err()
  	}
  
  	// Parse JSON into target.
  	if err := json.Unmarshal(bytes, target); err != nil {
  		return errors.Annotate(
  			err, "failed to decode JSON %q from %q", bytes, url).Err()
  	}
  
  	// Save data into memcache on a best-effort basis.
  	item.SetValue(bytes).SetExpiration(expiration)
  	if err = memcache.Set(c, item); err != nil {
  		logging.WithError(err).Warningf(c, "could not save url data %q into memcache", url)
  	}
  	return nil
  }
docs: // getJSONData fetches data from the given URL into the target, caching it
  // for expiration seconds in memcache.