remixr 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/History ADDED
@@ -0,0 +1 @@
1
+ 0.0.1 - initial release
data/License ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Squeejee
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Notes ADDED
File without changes
@@ -0,0 +1,76 @@
1
+ # remixr
2
+
3
+ The Ruby BestBuy [Remix API](http://remix.bestbuy.com/docs) gem. Remix is an API that gives you access to BestBuy.com's product catalog data and more.
4
+
5
+ ## Install
6
+
7
+ sudo gem install remixr
8
+
9
+ ## Usage
10
+
11
+ Remixr.api_key = 'OU812' # get yours from http://remix.bestbuy.com/apps/register
12
+ client = Remixr::Client.new
13
+
14
+ ### Find stores
15
+
16
+ # find stores within 50 miles of ZIP 76227
17
+ stores = client.stores({:area => ['76227', 50]}).fetch.stores
18
+
19
+ stores.first
20
+
21
+ => {"city"=>"Denton", "longName"=>"Best Buy - Denton", "name"=>"Denton", "region"=>"TX", "address"=>"1800 S Loop 288, Ste 102 Bldg 1 ", "country"=>"US", "lng"=>-97.10067, "postalCode"=>"76205", "phone"=>"940-384-9581", "hours"=>"Mon: 10-9; Tue: 10-9; Wed: 10-9; Thurs: 10-9; Fri: 10-10; Sat: 10-10; Sun: 11-8", "storeId"=>827, "fullPostalCode"=>"76205", "lat"=>33.192524, "distance"=>9.79}
22
+
23
+
24
+ ### Find products
25
+
26
+ # fetch first page of products on sale below 20 bucks
27
+ products = client.products({:salePrice => {'$lt' => 20.00}}).fetch.products
28
+
29
+ # fetch only SKU and salePrice
30
+ products = client.products({:salePrice => {'$lt' => 20.00}}).fetch.products
31
+
32
+ ### Chaining
33
+
34
+ You can also chain `stores` and `products` to return stores and nested product info or vice versa
35
+
36
+ # find stores within 50 miles of ZIP 76227 and products over three G's
37
+
38
+ stores = client.stores({:area => ['76227', 50]}).products({:salePrice => {'$gt' => 3000}}).fetch.stores
39
+
40
+ stores.first.products.first.shortDescription
41
+
42
+ #=> "ENERGY STAR Qualified 4 HDMI inputs; gray Touch of Color bezel; 16:9 aspect ratio"
43
+
44
+ ### Fetching
45
+
46
+ All calls terminate in a call to `fetch` which takes the following options
47
+
48
+ :page - positive integer for page number
49
+ :show - comma delimited string or array of field names to show
50
+ :sort - hash or string of sort info {'fieldname' => 'asc|desc'}
51
+
52
+
53
+ ### Conditional operators
54
+
55
+ We took a page out of [MongoDB's](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ConditionalOperators%3A%3C%2C%3C%3D%2C%3E%2C%3E%3D) playbook and mapped conditional operators to text equivalents to avoid having these be keys to hashes:
56
+
57
+ {:salePrice => {'$gte' => 300.00}}
58
+ => salePrice > 300.00
59
+
60
+ $gte - greater than or equal to : field > value
61
+ $lte - less than or equal to : field > value
62
+ $gt - greater than : field > value
63
+ $lt - less than : field > value
64
+ $ne - not equal to : field != value
65
+
66
+ More in the examples folder:
67
+
68
+ [http://github.com/squeejee/remixr/tree/master/examples](http://github.com/squeejee/remixr/tree/master/examples)
69
+
70
+ ### Documentation
71
+
72
+ [http://rdoc.info/projects/squeejee/remixr](http://rdoc.info/projects/squeejee/remixr)
73
+
74
+ #### Copyright
75
+
76
+ Copyright (c) 2009 Squeejee. See LICENSE for details.
@@ -0,0 +1,103 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "remixr"
8
+ gem.description = %Q{wrapper for the BestBuy Remix api}
9
+ gem.summary = %Q{wrapper for the BestBuy Remix api}
10
+ gem.email = "wynn@squeejee.com"
11
+ gem.homepage = "http://github.com/squeejee/remixr"
12
+ gem.authors = ["Wynn Netherland", "Jim Mulholland"]
13
+ gem.rubyforge_project = "remixr"
14
+ gem.files = FileList["[A-Z]*", "{examples,lib,test}/**/*"]
15
+
16
+ gem.add_dependency('mash', '0.0.3')
17
+ gem.add_dependency('httparty', '0.4.3')
18
+
19
+ gem.add_development_dependency('thoughtbot-shoulda')
20
+ gem.add_development_dependency('jeremymcanally-matchy')
21
+ gem.add_development_dependency('mocha')
22
+ gem.add_development_dependency('fakeweb')
23
+ gem.add_development_dependency('mash')
24
+ end
25
+ rescue LoadError
26
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
27
+ end
28
+
29
+ require 'rake/testtask'
30
+ Rake::TestTask.new(:test) do |test|
31
+ test.libs << 'lib' << 'test'
32
+ test.pattern = 'test/**/*_test.rb'
33
+ test.verbose = false
34
+ end
35
+
36
+ begin
37
+ require 'rcov/rcovtask'
38
+ Rcov::RcovTask.new do |test|
39
+ test.libs << 'test'
40
+ test.pattern = 'test/**/*_test.rb'
41
+ test.verbose = true
42
+ end
43
+ rescue LoadError
44
+ task :rcov do
45
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
46
+ end
47
+ end
48
+
49
+
50
+ task :default => :test
51
+
52
+ require 'rake/rdoctask'
53
+ Rake::RDocTask.new do |rdoc|
54
+ if File.exist?('VERSION.yml')
55
+ config = YAML.load(File.read('VERSION.yml'))
56
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
57
+ else
58
+ version = ""
59
+ end
60
+
61
+ rdoc.rdoc_dir = 'rdoc'
62
+ rdoc.title = "remixr #{version}"
63
+ rdoc.rdoc_files.include('README*')
64
+ rdoc.rdoc_files.include('lib/**/*.rb')
65
+ end
66
+
67
+ begin
68
+ require 'rake/contrib/sshpublisher'
69
+ namespace :rubyforge do
70
+
71
+ desc "Release gem and RDoc documentation to RubyForge"
72
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
73
+
74
+ namespace :release do
75
+ desc "Publish RDoc to RubyForge."
76
+ task :docs => [:rdoc] do
77
+ config = YAML.load(
78
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
79
+ )
80
+
81
+ host = "#{config['username']}@rubyforge.org"
82
+ remote_dir = "/var/www/gforge-projects/remixr/rdoc"
83
+ local_dir = 'rdoc'
84
+
85
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
86
+ end
87
+
88
+ # task :website do
89
+ # config = YAML.load(
90
+ # File.read(File.expand_path('~/.rubyforge/user-config.yml'))
91
+ # )
92
+ #
93
+ # host = "#{config['username']}@rubyforge.org"
94
+ # remote_dir = "/var/www/gforge-projects/remixr/"
95
+ # local_dir = 'website'
96
+ #
97
+ # Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
98
+ # end
99
+ end
100
+ end
101
+ rescue LoadError
102
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
103
+ end
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 0
3
+ :major: 0
4
+ :minor: 1
@@ -0,0 +1,7 @@
1
+ Remixr.api_key = 'OU812' # get yours from http://remix.bestbuy.com/apps/register
2
+ client = Remixr::Client.new
3
+
4
+ # find stores within 50 miles of ZIP 76227 and products over three G's
5
+ stores = client.stores({:area => ['76227', 50]}).products({:salePrice => {'$gt' => 3000}}).fetch.stores
6
+ stores.first.products.first.shortDescription
7
+ #=> "ENERGY STAR Qualified 4 HDMI inputs; gray Touch of Color bezel; 16:9 aspect ratio"
@@ -0,0 +1,13 @@
1
+ Remixr.api_key = 'OU812' # get yours from http://remix.bestbuy.com/apps/register
2
+ client = Remixr::Client.new
3
+
4
+ # fetch first page of products on sale below 20 bucks
5
+ products = client.products({:salePrice => {'$lt' => 20.00}}).fetch.products
6
+
7
+ products.first
8
+ # => {"url"=>"http://www.bestbuy.com/site/olspage.jsp?skuId=7524468&type=product&id=1494684&cmp=RMX&ky=1uYnAnk1pohGgQVwEClo8PHv4SN4C5MeL", "inStoreAvailability"=>true, "albumLabel"=>nil, "genre"=>nil, "sku"=>7524468, "affiliateUrl"=>nil, "cjAffiliateAddToCartUrl"=>nil, "salesRankLongTerm"=>2451, "addToCartUrl"=>"http://www.bestbuy.com/site/olspage.jsp?id=pcmcat152200050035&type=category&cmp=RMX&ky=1uYnAnk1pohGgQVwEClo8PHv4SN4C5MeL&qvsids=7524468", "remoteControlImage"=>nil, "affiliateAddToCartUrl"=>nil, "largeImage"=>nil, "new"=>false, "salePrice"=>15.99, "artistId"=>"BYPart1061717", "inStoreAvailabilityUpdateDate"=>"2007-07-27T20:20:50", "largeFrontImage"=>nil, "department"=>"VIDEO/COMPACT DISC", "artistName"=>"Purple City", "accessoriesImage"=>nil, "format"=>"CD", "customerReviewCount"=>nil, "regularPrice"=>15.99, "amgId"=>nil, "freeShipping"=>false, "salesRankShortTerm"=>250, "shortDescription"=>nil, "specialOrder"=>false, "nationalFeatured"=>false, "manufacturer"=>nil, "salesRankMediumTerm"=>570, "energyGuideImage"=>nil, "inStoreAvailabilityText"=>"Store Pickup: Limited Availability", "alternateViewsImage"=>nil, "mobileUrl"=>"http://m.bestbuy.com/r/1494684/7524468/", "subclass"=>"RAP", "name"=>"\"Paris to Purple City\"", "cjAffiliateUrl"=>nil, "image"=>"http://images.bestbuy.com/BestBuy_US/images/products/7524/7524468.jpg", "shippingCost"=>1.59, "subclassId"=>1009, "upc"=>"823979901426", "onlineAvailabilityText"=>"Shipping: Usually leaves our warehouse in 1 business day", "onlineAvailabilityUpdateDate"=>"2007-07-27T20:20:50", "topViewImage"=>nil, "class"=>"COMPACT DISC", "active"=>true, "classId"=>77, "parentalAdvisory"=>false, "thumbnailImage"=>"http://images.bestbuy.com/BestBuy_US/images/products/7524/7524468s.jpg", "leftViewImage"=>nil, "rightViewImage"=>nil, "productId"=>1494684, "source"=>"bestbuy", "customerReviewAverage"=>nil, "activeUpdateDate"=>"2007-07-27T20:20:50", "mediumImage"=>nil, "startDate"=>#<Date: 4906945/2,0,2299161>, "departmentId"=>8, "angleImage"=>nil, "albumVersion"=>nil, "spin360Url"=>nil, "priceUpdateDate"=>"2008-02-09T00:10:37", "categoryPath"=>[<Mash id="cat00000" name="Best Buy">, <Mash id="abcat0600000" name="Music & Movies">, <Mash id="cat02001" name="Music">, <Mash id="cat02012" name="Rap & Hip-Hop">, <Mash id="cat02719" name="Rap">], "printOnly"=>false, "releaseDate"=>#<Date: 4907365/2,0,2299161>, "search"=>nil, "copyright"=>nil, "onSale"=>false, "itemUpdateDate"=>"2009-02-03T03:50:13", "albumTitle"=>"\"Paris to Purple City\"", "type"=>"Music", "originalReleaseDat
9
+
10
+
11
+ # fetch only SKU and salePrice
12
+ products = client.products({:salePrice => {'$lt' => 20.00}}).fetch.products
13
+ # => [{"salePrice"=>10.99, "sku"=>7000032}, {"salePrice"=>10.99, "sku"=>11467058}, {"salePrice"=>13.99, "sku"=>7873884}, {"salePrice"=>11.99, "sku"=>15444798}, {"salePrice"=>13.99, "sku"=>9113256}, {"salePrice"=>13.99, "sku"=>5797649}, {"salePrice"=>13.99, "sku"=>8890961}, {"salePrice"=>14.99, "sku"=>17338506}, {"salePrice"=>11.99, "sku"=>9242642}, {"salePrice"=>13.99, "sku"=>9171353}]
@@ -0,0 +1,11 @@
1
+ Remixr.api_key = 'OU812' # get yours from http://remix.bestbuy.com/apps/register
2
+ client = Remixr::Client.new
3
+
4
+ # find stores within 50 miles of ZIP 76227
5
+ stores = client.stores({:area => ['76227', 50]}).fetch.stores
6
+
7
+ stores.first
8
+ # => {"city"=>"Denton", "longName"=>"Best Buy - Denton", "name"=>"Denton", "region"=>"TX", "address"=>"1800 S Loop 288, Ste 102 Bldg 1 ", "country"=>"US", "lng"=>-97.10067, "postalCode"=>"76205", "phone"=>"940-384-9581", "hours"=>"Mon: 10-9; Tue: 10-9; Wed: 10-9; Thurs: 10-9; Fri: 10-10; Sat: 10-10; Sun: 11-8", "storeId"=>827, "fullPostalCode"=>"76205", "lat"=>33.192524, "distance"=>9.79}
9
+
10
+
11
+
@@ -0,0 +1,29 @@
1
+ require 'forwardable'
2
+ require 'rubygems'
3
+
4
+ gem 'mash', '0.0.3'
5
+ require 'mash'
6
+
7
+ gem 'httparty', '0.4.3'
8
+ require 'httparty'
9
+
10
+ class APIKeyNotSet < StandardError; end
11
+
12
+ module Remixr
13
+
14
+ # Get your API key from http://remix.bestbuy.com/apps/register
15
+ def self.api_key
16
+ raise APIKeyNotSet if @api_key.nil?
17
+
18
+ @api_key
19
+ end
20
+
21
+ def self.api_key=(api_key)
22
+ @api_key = api_key
23
+ end
24
+
25
+ end
26
+
27
+ directory = File.expand_path(File.dirname(__FILE__))
28
+
29
+ require File.join(directory, 'remixr', 'client')
@@ -0,0 +1,157 @@
1
+ module Remixr
2
+ class Client
3
+ include HTTParty
4
+ base_uri 'api.remix.bestbuy.com/v1'
5
+ format :json
6
+
7
+ attr_reader :api_key, :store_filters, :product_filters
8
+
9
+ # Get your api_key found here http://remix.bestbuy.com/apps/register
10
+ def initialize(api_key=nil)
11
+ @api_key = api_key
12
+ @api_key ||= Remixr.api_key
13
+
14
+ @api_path = ''
15
+ @store_filters = {}
16
+ @product_filters = {}
17
+ end
18
+
19
+ # Example filters:
20
+ # Stores within 50 miles of ZIP 76227
21
+ # stores({:area => [76227,50]})
22
+ # GET /v1/stores(area(76227,50))
23
+ #
24
+ # Stores west of the Pecos
25
+ # stores({:lng => {'$lt' => -104.304199}})
26
+ # GET /v1/stores(lng>-104.304199)
27
+ #
28
+ def stores(filters={})
29
+ unless @api_path.include?('stores()')
30
+ @api_path += '+' unless @api_path.blank?
31
+ @api_path += "stores()"
32
+ end
33
+ @store_filters.merge!(filters)
34
+ self
35
+ end
36
+
37
+ # Convenience method for finding a store by zip
38
+ # stores.in_zip(76227)
39
+ # GET /v1/stores(postalCode=76227)
40
+ def in_zip(zip)
41
+ self.stores({'postalCode' => zip})
42
+ end
43
+
44
+ # Convenience method for finding a store by region
45
+ # stores.in_region('TX')
46
+ # GET /v1/stores(region=TX)
47
+ def in_region(region)
48
+ self.stores({'region' => region})
49
+ end
50
+
51
+ # Example filters:
52
+ # Products under 20 bucks
53
+ # products({:salePrice => {'$lt' => 20.00}})
54
+ # GET /v1/products(salePrice<20.00)
55
+ def products(filters={})
56
+ unless @api_path.include?('products()')
57
+ @api_path += '+' unless @api_path.blank?
58
+ @api_path += "products()"
59
+ end
60
+ @product_filters.merge!(filters)
61
+ self
62
+ end
63
+
64
+
65
+ # Executes the search
66
+ # Possible options:
67
+ # :page - positive integer for page number
68
+ # :show - comma delimited string or array of field names to show
69
+ # :sort - hash or string of sort info {'fieldname' => 'asc|desc'}
70
+ def fetch(options={})
71
+ opts = {:apiKey => @api_key, :format => 'json'}
72
+ opts.merge!(scrub_options(options))
73
+
74
+ apply_store_filters
75
+ apply_product_filters
76
+ @api_path = URI.escape(@api_path)
77
+ response = self.class.get("/" + @api_path, :query => opts)
78
+ @api_path = ''
79
+ Mash.new response
80
+ end
81
+
82
+ private
83
+ def apply_store_filters
84
+ if @store_filters.keys.blank?
85
+ @api_path.gsub!("stores()", "stores")
86
+ else
87
+ @api_path.gsub!("stores()", "stores(#{filter_params_string(@store_filters)})")
88
+ end
89
+ end
90
+
91
+ def apply_product_filters
92
+ if @product_filters.keys.blank?
93
+ @api_path.gsub!("products()", "products")
94
+ else
95
+ @api_path.gsub!("products()", "products(#{filter_params_string(@product_filters)})")
96
+ end
97
+ end
98
+
99
+ def filter_params_string(filters)
100
+ return "" unless filters.is_a?(Hash)
101
+
102
+ filters = Mash.new filters.to_hash # calling Mash.new on a mash is bad mmmm k?
103
+ params = []
104
+ filters.each do |key, value|
105
+ if value.is_a?(Hash)
106
+ inner_hash = value
107
+ case inner_hash.keys.first
108
+ when "$gt"
109
+ params << "#{key}>#{inner_hash.values.first}"
110
+ when "$lt"
111
+ params << "#{key}<#{inner_hash.values.first}"
112
+ when "$gte"
113
+ params << "#{key}>=#{inner_hash.values.first}"
114
+ when "$lte"
115
+ params << "#{key}<=#{inner_hash.values.first}"
116
+ when "$ne"
117
+ params << "#{key}!=#{inner_hash.values.first}"
118
+ when "$in"
119
+ params << "#{key} in(#{inner_hash.values.first.join(',')})"
120
+ end
121
+ elsif value.is_a?(Array)
122
+ params << "#{key}(#{value.join(',')})"
123
+ else
124
+ params << "#{key}=#{value}"
125
+ end
126
+ end
127
+
128
+ if params.blank?
129
+ ""
130
+ else
131
+ "#{params.join('&')}"
132
+ end
133
+ end
134
+
135
+ def scrub_options(options)
136
+ options = Mash.new(options.to_hash)
137
+ show = options.delete('show')
138
+ unless show.blank?
139
+ if show.is_a?(String)
140
+ options['show'] = show
141
+ elsif show.is_a?(Array)
142
+ options['show'] = show.join(',')
143
+ end
144
+ end
145
+ sort = options.delete('sort')
146
+ unless sort.blank?
147
+ if sort.is_a?(Hash)
148
+ options['sort'] = "#{sort.keys.first}.#{sort.values.first}"
149
+ else
150
+ options['sort'] = sort
151
+ end
152
+ end
153
+ options
154
+ end
155
+
156
+ end
157
+ end
@@ -0,0 +1,216 @@
1
+ {
2
+ "totalPages": 1,
3
+ "currentPage": 1,
4
+ "queryTime": "0.346",
5
+ "from": 1,
6
+ "products": [
7
+ {
8
+ "shippingWeight": ".2208",
9
+ "printOnly": false,
10
+ "description": null,
11
+ "url": "http:\/\/www.bestbuy.com\/site\/olspage.jsp?skuId=4660432&type=product&id=1051806199755&cmp=RMX&ky=1uYnAnk1pohGgQVwEClo8PHv4SN4C5MeL",
12
+ "inStoreAvailability": true,
13
+ "sku": 4660432,
14
+ "cjAffiliateAddToCartUrl": null,
15
+ "search": null,
16
+ "addToCartUrl": "http:\/\/www.bestbuy.com\/site\/olspage.jsp?id=pcmcat152200050035&type=category&cmp=RMX&ky=1uYnAnk1pohGgQVwEClo8PHv4SN4C5MeL&qvsids=4660432",
17
+ "affiliateAddToCartUrl": null,
18
+ "new": false,
19
+ "accessoriesImage": null,
20
+ "weight": null,
21
+ "salePrice": 28.99,
22
+ "dollarSavings": 0.0,
23
+ "inStoreAvailabilityUpdateDate": "2009-01-21T01:34:16",
24
+ "largeFrontImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4660\/4660432_sa.jpg",
25
+ "freeShipping": true,
26
+ "navigability": true,
27
+ "height": null,
28
+ "color": "Photo Multicolor",
29
+ "remoteControlImage": null,
30
+ "largeImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4660\/4660432_sb.jpg",
31
+ "format": null,
32
+ "salesRankLongTerm": 1156,
33
+ "inStoreAvailabilityText": "Store Pickup: Available at most stores",
34
+ "regularPrice": 28.99,
35
+ "salesRankShortTerm": 244,
36
+ "nationalFeatured": false,
37
+ "manufacturer": "HP",
38
+ "onlineAvailabilityText": "Shipping: Usually leaves our warehouse in 1 business day",
39
+ "salesRankMediumTerm": 473,
40
+ "department": "PHOTO\/COMMODITIES",
41
+ "energyGuideImage": null,
42
+ "customerReviewCount": null,
43
+ "mobileUrl": "http:\/\/m.bestbuy.com\/r\/1051806199755\/4660432\/",
44
+ "name": "HP 58 Photo Inkjet Cartridge - Photo Multicolor",
45
+ "image": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4660\/4660432_sc.jpg",
46
+ "shippingCost": 0.0,
47
+ "shortDescription": "Compatible with specified HP Deskjet, Photosmart, all-in-one, Officejet and digital copier printers",
48
+ "specialOrder": false,
49
+ "customerReviewAverage": null,
50
+ "warrantyParts": null,
51
+ "depth": null,
52
+ "topViewImage": null,
53
+ "upc": "808736183857",
54
+ "class": "PAPER\/OFFICE SUPPLIE",
55
+ "departmentId": 5,
56
+ "active": true,
57
+ "classId": 117,
58
+ "subclass": "INK\/TONER SUPPLIES",
59
+ "rightViewImage": null,
60
+ "cjAffiliateUrl": null,
61
+ "priceUpdateDate": "2009-03-10T06:13:56",
62
+ "alternateViewsImage": null,
63
+ "warrantyLabor": null,
64
+ "source": "bestbuy",
65
+ "releaseDate": null,
66
+ "modelNumber": "C6658AN",
67
+ "longDescription": "Multicolor photo ink cartridge compatible with specified HP Deskjet, Photosmart, all-in-one, Officejet and digital copier printers. Fade-resistant.",
68
+ "onlineAvailabilityUpdateDate": "2009-01-21T01:34:16",
69
+ "startDate": "2002-08-04",
70
+ "subclassId": 402,
71
+ "angleImage": null,
72
+ "thumbnailImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4660\/4660432_s.gif",
73
+ "leftViewImage": null,
74
+ "type": "HardGood",
75
+ "productId": 1051806199755,
76
+ "orderable": "Available",
77
+ "categoryPath": [
78
+ {
79
+ "name": "Best Buy",
80
+ "id": "cat00000"
81
+ },
82
+ {
83
+ "name": "Cell Phones & Office",
84
+ "id": "abcat0800000"
85
+ },
86
+ {
87
+ "name": "Ink & Toner",
88
+ "id": "abcat0807000"
89
+ },
90
+ {
91
+ "name": "Ink",
92
+ "id": "abcat0807001"
93
+ },
94
+ {
95
+ "name": "Hewlett-Packard",
96
+ "id": "abcat0807005"
97
+ }
98
+ ],
99
+ "mediumImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4660\/4660432fp.gif",
100
+ "onSale": false,
101
+ "itemUpdateDate": "2009-07-28T19:23:43",
102
+ "affiliateUrl": null,
103
+ "activeUpdateDate": "2009-01-21T01:34:16",
104
+ "width": null,
105
+ "spin360Url": null,
106
+ "backViewImage": null,
107
+ "onlineAvailability": true
108
+ },
109
+ {
110
+ "shippingWeight": ".225",
111
+ "printOnly": false,
112
+ "description": null,
113
+ "url": "http:\/\/www.bestbuy.com\/site\/olspage.jsp?skuId=4312746&type=product&id=1051806147888&cmp=RMX&ky=1uYnAnk1pohGgQVwEClo8PHv4SN4C5MeL",
114
+ "inStoreAvailability": true,
115
+ "sku": 4312746,
116
+ "cjAffiliateAddToCartUrl": null,
117
+ "search": null,
118
+ "addToCartUrl": "http:\/\/www.bestbuy.com\/site\/olspage.jsp?id=pcmcat152200050035&type=category&cmp=RMX&ky=1uYnAnk1pohGgQVwEClo8PHv4SN4C5MeL&qvsids=4312746",
119
+ "affiliateAddToCartUrl": null,
120
+ "new": false,
121
+ "accessoriesImage": null,
122
+ "weight": null,
123
+ "salePrice": 39.99,
124
+ "dollarSavings": 0.0,
125
+ "inStoreAvailabilityUpdateDate": "2009-06-27T01:43:54",
126
+ "largeFrontImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4312\/4312746_sa.jpg",
127
+ "freeShipping": true,
128
+ "navigability": true,
129
+ "height": null,
130
+ "color": "Multicolor",
131
+ "remoteControlImage": null,
132
+ "largeImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4312\/4312746_sb.jpg",
133
+ "format": null,
134
+ "salesRankLongTerm": 599,
135
+ "inStoreAvailabilityText": "Store Pickup: Available at most stores",
136
+ "regularPrice": 39.99,
137
+ "salesRankShortTerm": 243,
138
+ "nationalFeatured": false,
139
+ "manufacturer": "HP",
140
+ "onlineAvailabilityText": "Shipping: Usually leaves our warehouse in 1 business day",
141
+ "salesRankMediumTerm": 473,
142
+ "department": "PHOTO\/COMMODITIES",
143
+ "energyGuideImage": null,
144
+ "customerReviewCount": 1,
145
+ "mobileUrl": "http:\/\/m.bestbuy.com\/r\/1051806147888\/4312746\/",
146
+ "name": "HP 57 Inkjet Cartridge - Multicolor",
147
+ "image": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4312\/4312746_sc.jpg",
148
+ "shippingCost": 0.0,
149
+ "shortDescription": "Compatible with specified HP Deskjet, Photosmart, all-in-one, Officejet and digital copier printers",
150
+ "specialOrder": false,
151
+ "customerReviewAverage": 5.0,
152
+ "warrantyParts": null,
153
+ "depth": null,
154
+ "topViewImage": null,
155
+ "upc": "725184712340",
156
+ "class": "PAPER\/OFFICE SUPPLIE",
157
+ "departmentId": 5,
158
+ "active": true,
159
+ "classId": 117,
160
+ "subclass": "INK\/TONER SUPPLIES",
161
+ "rightViewImage": null,
162
+ "cjAffiliateUrl": null,
163
+ "priceUpdateDate": "2009-03-10T00:13:56",
164
+ "alternateViewsImage": null,
165
+ "warrantyLabor": null,
166
+ "source": "bestbuy",
167
+ "releaseDate": null,
168
+ "modelNumber": "C6657AN",
169
+ "longDescription": "Tricolor ink cartridge creates bright, photo-quality color. Compatible with specified HP Deskjet, Photosmart, all-in-one, Officejet and digital copier printers",
170
+ "onlineAvailabilityUpdateDate": "2009-06-27T01:43:54",
171
+ "startDate": "2002-08-15",
172
+ "subclassId": 402,
173
+ "angleImage": null,
174
+ "thumbnailImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4312\/4312746_s.gif",
175
+ "leftViewImage": null,
176
+ "type": "HardGood",
177
+ "productId": 1051806147888,
178
+ "orderable": "Available",
179
+ "categoryPath": [
180
+ {
181
+ "name": "Best Buy",
182
+ "id": "cat00000"
183
+ },
184
+ {
185
+ "name": "Cell Phones & Office",
186
+ "id": "abcat0800000"
187
+ },
188
+ {
189
+ "name": "Ink & Toner",
190
+ "id": "abcat0807000"
191
+ },
192
+ {
193
+ "name": "Ink",
194
+ "id": "abcat0807001"
195
+ },
196
+ {
197
+ "name": "Hewlett-Packard",
198
+ "id": "abcat0807005"
199
+ }
200
+ ],
201
+ "mediumImage": "http:\/\/images.bestbuy.com\/BestBuy_US\/images\/products\/4312\/4312746fp.gif",
202
+ "onSale": false,
203
+ "itemUpdateDate": "2009-07-28T19:21:16",
204
+ "affiliateUrl": null,
205
+ "activeUpdateDate": "2009-06-27T01:43:54",
206
+ "width": null,
207
+ "spin360Url": null,
208
+ "backViewImage": null,
209
+ "onlineAvailability": true
210
+ }
211
+ ],
212
+ "total": 2,
213
+ "to": 2,
214
+ "canonicalUrl": "\/v1\/products(|)?format=json&apiKey=OU812",
215
+ "totalTime": "0.351"
216
+ }